From 49aba51e6bfd3f6d59c0f28628cc983d84438cfa Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Sat, 8 Oct 2016 15:17:37 +0100 Subject: [PATCH] feat(Module): add `info()` method The new `info()` method lets developers store arbitrary information about their module for consumption later. Closes #15225 --- docs/content/error/ng/aobj.ngdoc | 7 ++++++ src/loader.js | 42 ++++++++++++++++++++++++++++++++ test/loaderSpec.js | 31 +++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 docs/content/error/ng/aobj.ngdoc diff --git a/docs/content/error/ng/aobj.ngdoc b/docs/content/error/ng/aobj.ngdoc new file mode 100644 index 000000000000..101fb172393b --- /dev/null +++ b/docs/content/error/ng/aobj.ngdoc @@ -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. diff --git a/src/loader.js b/src/loader.js index 36da047fe20b..05c24ce3e28f 100644 --- a/src/loader.js +++ b/src/loader.js @@ -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'); + info = value; + return this; + } + return info; + }, + /** * @ngdoc property * @name angular.Module#requires diff --git a/test/loaderSpec.js b/test/loaderSpec.js index c4f7a33989bd..7166f218c3e8 100644 --- a/test/loaderSpec.js +++ b/test/loaderSpec.js @@ -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' }); + }); + + 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' }); + }); + }); + }); });