-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Conversation
src/loader.js
Outdated
* {@link $injector#modules `$injector.modules`} property: | ||
* | ||
* ```js | ||
* var version = $injector.modules['myModule'].info().version; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't angular.module('myModule').info()
also work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but in that case you do know, necessarily if the module was
a) loaded in the first place
b) added to the injector
If it was not loaded then your line of code would throw an exception
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean use it in place of $injector.modules['myModule'].info()
- i.e. at "runtime" - so it should have been added to the injector.
I was mainly curious basically. $injector.modules['myModule']
works for me 😃
Hm...since we brought it up, $injector
is kind of ambiguous, since it may refer to the providerInjector
(which doesn't know about modules
) or the instanceInjector
(which does).
I doubt anyone is using the providerInjector
, but still it might be a good idea to add modules
on the providerInjector
as well (for symmetry).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow. You can't use angular.module('myModule').info()
since you don't know if that module has been loaded or included in the current app.
In fact, you don't even know what the current app is since there might be more than one bootstrapped on a page.
Also, $injector
is not ambiguous. It is the only injector that you can inject into components and services, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But maybe I'm missing the point...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think he's referring to the $injector
that you can inject into config
function which is not the same injector as is injected into a service, component, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I am referring to the providerInjector
that can be injected into providers/config blocks. E.g.:
.provider('foo', ['$injector', function fooProvider(providerInjector) {
this.$get = ['$injector', function foo(instanceInjector) {
console.log(providerInjector === instanceInjector); // false
}
})
(Again, I don't expect many people to be actually using it, but you never know 😃)
Regarding angular.module('someModule').info()
:
Assume you are the author of a library or addon that relies on another library (e.g. myAwesomeMaterialToolbar
). You can request that your addon is loaded after ngMaterial
, so you can detect its version and do different things. E.g.:
// my-awesome-material-toolbar.js
var mdVersion = angular.module('ngMaterial').info().version;
var deps = (mdVersion >= '1.1.1') ? [] : ['myShimForAFeatureAddedInNgMaterial1.1.1'];
angular.module('myAwesomeMaterialToolbar', deps);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will fix the providerInjector/instanceInjector thing.
Regarding the load time dependencies use case. For sure you can do what you suggest with the functionality provided in this PR, although you are having to ensure that the developer loads the script files in the correct order and is not using some async loading helper that might mess things up.
It would be safer (IMO) to do configuration of your awesome library in providers, etc... Although I accept it is difficult to optionally add in a directive, you could make the directive a noop if not wanted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me 👍
src/loader.js
Outdated
* or `this` if called as a setter. | ||
* | ||
* @description | ||
* Additional info about this module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes it sound as if passing an object would extend the existing info (not overwrite it).
I think we should be pretty explicit about that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
|
||
it('should store the object passed as a param', function() { | ||
theModule.info({ version: '1.2' }); | ||
expect(theModule.info()).toEqual({ version: '1.2' }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a test to verify it overwrites the previous info object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
8a38763
to
8c4dd97
Compare
PTAL @gkalpak |
*/ | ||
info: function(value) { | ||
if (isDefined(value)) { | ||
if (!isObject(value)) throw ngMinErr('aobj', 'Argument \'{0}\' must be an object', 'value'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be value
instead of 'value'
(i.e. without the quotes), right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I don't think so. The idea is that the error can be general and be used with other parameters names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Then why do you need the {0}
? Why don't you just write 'Argument \'value\' must be an object'
directly? I guess in order to make it easier to recognize the part that is interchangeable.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not 100% sure but I think that the format string has to be consistent for all usage of the error.
var test1 = angular.module('test1', ['test2']).info({ version: '1.1' }); | ||
var test2 = angular.module('test2', []).info({ version: '1.2' }); | ||
module('test1'); | ||
inject(['$injector', function($injector) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OOC, is the array necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't we decide to make all our tests minification proof?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure there was an issue about it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't remember anything like that (why would we)?
Maybe we have decided to make ngMocks
minification-safe (because it makes it easier for some people to incorporate it into their workflow), but not our tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They don't have to be minification-proof but shouldn't we aim at making them pass in strict DI mode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is not such thing as "strict DI" in tests :)
(Also none of the other tests are, so it is obviously not a problem.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is not such thing as "strict DI" in tests :)
What I meant by that is that we are manually annotating the injected functions, if strict DI is enabled.
LGTM (with or without the array notation 😃) |
Thanks @gkalpak - I just thought we should check that there is something similar in A2 before landing this. |
So in Angular there is the |
8c4dd97
to
8a12a75
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered "version-stamping" ngLocale
?
@@ -265,5 +265,6 @@ function publishExternalAPI(angular) { | |||
$$cookieReader: $$CookieReaderProvider | |||
}); | |||
} | |||
]); | |||
]) | |||
.info({ angularVersion: '"NG_VERSION_FULL"' }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not call it just version
(since it's already namespaced by the module name).
Especially in other modules (ngAnimate
, ngAria
, etc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I was leaning towards the idea that you would stamp your module with the version of Angular that it was designed for, rather than the version of the module itself...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me angularVersion
seems more intuitive; otherwise I'd feel we're talking about the module version as Pete said.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tend to think it as the module version indeed. But it doesn't make any real difference. angularVersion
works for me.
972e0a2
to
13326ee
Compare
I will add version stamping to the locale modules too. |
It turns out that adding the version stamp to the locale files is a little more involved with changes to grunt required :-( |
Sounds like it's not worth it. It still LGTM without vervion-stamping locale files 😃 |
The new `info()` method lets developers store arbitrary information about their module for consumption later.
The `modules` property is a hash of the modules loaded into the injector at bootstrap time. This can be used to access the module's info.
You can now check what version of AngularJS a core module is designed for: ``` var angularVersion = $injector.modules['myModule'].info().angularVersion; ```
13326ee
to
2a5a410
Compare
The new `info()` method lets developers store arbitrary information about their module for consumption later. Closes #15225
The new `info()` method lets developers store arbitrary information about their module for consumption later. Closes angular#15225
What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
feature
What is the current behavior? (You can also link to an open issue here)
No way to find information about the currently loaded modules
What is the new behavior (if this is a feature change)?
Two new features:
Module
(info()
) that lets developers add arbitrary info about their modules.$injector
(modules
) that lets developers access the module objects that were loaded into the injector at bootstrap.This second item could also be useful to @ocombe for his ocLazyLoad project.
Does this PR introduce a breaking change?
No
Please check if the PR fulfills these requirements
Other information:
Replaces the previous #12465 PR