-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Module info #15225
Module info #15225
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
@ngdoc error | ||
@name ng:aobj | ||
@fullName Invalid Argument | ||
@description | ||
|
||
The argument passed should be an object. Check the value that was passed to the function where | ||
this error was thrown. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,6 +79,9 @@ function setupModuleLoader(window) { | |
* @returns {angular.Module} new module with the {@link angular.Module} api. | ||
*/ | ||
return function module(name, requires, configFn) { | ||
|
||
var info = {}; | ||
|
||
var assertNotHasOwnProperty = function(name, context) { | ||
if (name === 'hasOwnProperty') { | ||
throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); | ||
|
@@ -114,6 +117,45 @@ function setupModuleLoader(window) { | |
_configBlocks: configBlocks, | ||
_runBlocks: runBlocks, | ||
|
||
/** | ||
* @ngdoc method | ||
* @name angular.Module#info | ||
* @module ng | ||
* | ||
* @param {Object=} info Information about the module | ||
* @returns {Object|Module} The current info object for this module if called as a getter, | ||
* or `this` if called as a setter. | ||
* | ||
* @description | ||
* Read and write custom information about this module. | ||
* For example you could put the version of the module in here. | ||
* | ||
* ```js | ||
* angular.module('myModule', []).info({ version: '1.0.0' }); | ||
* ``` | ||
* | ||
* The version could then be read back out by accessing the module elsewhere: | ||
* | ||
* ``` | ||
* var version = angular.module('myModule').info().version; | ||
* ``` | ||
* | ||
* You can also retrieve this information during runtime via the | ||
* {@link $injector#modules `$injector.modules`} property: | ||
* | ||
* ```js | ||
* var version = $injector.modules['myModule'].info().version; | ||
* ``` | ||
*/ | ||
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 commentThe reason will be displayed to describe this comment to others. Learn more. This should probably be There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Right. Then why do you need the There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
info = value; | ||
return this; | ||
} | ||
return info; | ||
}, | ||
|
||
/** | ||
* @ngdoc property | ||
* @name angular.Module#requires | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,37 @@ | |
|
||
/* globals support: false */ | ||
|
||
describe('injector.modules', function() { | ||
it('should expose the loaded module info on the instance injector', function() { | ||
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 commentThe 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 commentThe 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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. I don't remember anything like that (why would we)? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. There is not such thing as "strict DI" in tests :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What I meant by that is that we are manually annotating the injected functions, if strict DI is enabled. |
||
expect(Object.keys($injector.modules)).toEqual(['ng', 'ngLocale', 'ngMock', 'test1', 'test2']); | ||
expect($injector.modules['test1'].info()).toEqual({ version: '1.1' }); | ||
expect($injector.modules['test2'].info()).toEqual({ version: '1.2' }); | ||
}]); | ||
}); | ||
|
||
it('should expose the loaded module info on the provider injector', function() { | ||
var providerInjector; | ||
var test1 = angular.module('test1', ['test2']).info({ version: '1.1' }); | ||
var test2 = angular.module('test2', []) | ||
.info({ version: '1.2' }) | ||
.provider('test', ['$injector', function($injector) { | ||
providerInjector = $injector; | ||
return { $get: function() {} }; | ||
}]); | ||
module('test1'); | ||
// needed to ensure that the provider blocks are executed | ||
inject(); | ||
|
||
expect(Object.keys(providerInjector.modules)).toEqual(['ng', 'ngLocale', 'ngMock', 'test1', 'test2']); | ||
expect(providerInjector.modules['test1'].info()).toEqual({ version: '1.1' }); | ||
expect(providerInjector.modules['test2'].info()).toEqual({ version: '1.2' }); | ||
}); | ||
}); | ||
|
||
describe('injector', function() { | ||
var providers; | ||
var injector; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -156,4 +156,35 @@ describe('module loader', function() { | |
it('should expose `$$minErr` on the `angular` object', function() { | ||
expect(window.angular.$$minErr).toEqual(jasmine.any(Function)); | ||
}); | ||
|
||
describe('Module', function() { | ||
describe('info()', function() { | ||
var theModule; | ||
|
||
beforeEach(function() { | ||
theModule = angular.module('theModule', []); | ||
}); | ||
|
||
it('should default to an empty object', function() { | ||
expect(theModule.info()).toEqual({}); | ||
}); | ||
|
||
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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. OK |
||
}); | ||
|
||
it('should throw if the parameter is not an object', function() { | ||
expect(function() { | ||
theModule.info('some text'); | ||
}).toThrowMinErr('ng', 'aobj'); | ||
}); | ||
|
||
it('should completely replace the previous info object', function() { | ||
theModule.info({ value: 'X' }); | ||
theModule.info({ newValue: 'Y' }); | ||
expect(theModule.info()).toEqual({ newValue: 'Y' }); | ||
}); | ||
}); | ||
}); | ||
}); |
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.