diff --git a/src/ng/compile.js b/src/ng/compile.js index b21e8a09165e..21374076caf7 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -792,7 +792,21 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/, CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/, ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'), - REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; + REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/, + ALIASED_COMPONENT_OPTIONS = { + bindToController: 'bindings' + }, + UNSUPPORTED_COMPONENT_OPTIONS = [ + 'compile', + 'link', + 'multiElement', + 'priority', + 'replace', + 'restrict', + 'scope', + 'templateNamespace', + 'terminal' + ]; // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes // The assumption is that future DOM event attribute names will begin with @@ -876,6 +890,32 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } } + function verifyComponentOptions(options, componentName, $log) { + var optionKeys = Object.keys(options); + + var unsupportedOpts = UNSUPPORTED_COMPONENT_OPTIONS.filter(isUsed); + if (unsupportedOpts.length) { + var warning = 'The following unsupported options were detected in the "' + componentName + + '" component\'s Definition Object:\n ' + unsupportedOpts.join(', ') + '\n' + + 'Their values will be ignored or overwritten. If you need these features, ' + + 'you can use `.directive()` instead.'; + $log.debug(warning); + } + + var aliasedOpts = Object.keys(ALIASED_COMPONENT_OPTIONS).filter(isUsed); + aliasedOpts.forEach(function(opt) { + var alias = ALIASED_COMPONENT_OPTIONS[opt]; + var warning = 'The "' + opt + '" option (used in the "' + componentName + '" component\'s ' + + 'Definition Object) will have no effect. For components, use "' + alias + + '" instead.'; + $log.debug(warning); + }); + + function isUsed(opt) { + return optionKeys.indexOf(opt) !== -1; + } + } + /** * @ngdoc method * @name $compileProvider#directive @@ -1059,7 +1099,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { this.component = function registerComponent(name, options) { var controller = options.controller || function() {}; - function factory($injector) { + function factory($injector, $log) { function makeInjectable(fn) { if (isFunction(fn) || isArray(fn)) { return function(tElement, tAttrs) { @@ -1070,6 +1110,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } } + verifyComponentOptions(options, name, $log); + var template = (!options.template && !options.templateUrl ? '' : options.template); return { controller: controller, @@ -1091,7 +1133,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } }); - factory.$inject = ['$injector']; + factory.$inject = ['$injector', '$log']; return this.directive(name, factory); }; diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index f885d3106433..a7bffcf3813e 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -9334,6 +9334,66 @@ describe('$compile', function() { })); }); + they('should log a warning for the unsupported option(s) $prop', [ + 'compile', + 'link', + 'multiElement', + 'priority', + 'replace', + 'restrict', + 'scope', + 'templateNamespace', + 'terminal', + 'restrict, scope', + 'compile, link, multiElement, priority, replace, templateNamespace, terminal' + ], function(optionStr) { + var warning = 'The following unsupported options were detected in the "myComponent' + + '" component\'s Definition Object:\n ' + optionStr + '\n' + + 'Their values will be ignored or overwritten. If you need these features, ' + + 'you can use `.directive()` instead.'; + + module(function($compileProvider) { + var cdo = {controller: function(log) { log('OK'); }}; + optionStr.split(', ').forEach(function(opt) { cdo[opt] = true; }); + + $compileProvider.component('myComponent', cdo); + }); + + inject(function($compile, $log, $rootScope, log) { + spyOn($log, 'debug'); + element = $compile('')($rootScope); + + expect($log.debug).toHaveBeenCalledOnceWith(warning); + expect(log).toEqual('OK'); + }); + }); + + they('should log a warning for the aliased option(s) $prop', { + bindToController: {option: 'bindToController', alias: 'bindings'} + }, function(data) { + var option = data.option; + var alias = data.alias; + + var warning = 'The "' + option + '" option (used in the "myComponent" component\'s ' + + 'Definition Object) will have no effect. For components, use "' + alias + + '" instead.'; + + module(function($compileProvider) { + var cdo = {controller: function(log) { log('OK'); }}; + cdo[option] = true; + + $compileProvider.component('myComponent', cdo); + }); + + inject(function($compile, $log, $rootScope, log) { + spyOn($log, 'debug'); + element = $compile('')($rootScope); + + expect($log.debug).toHaveBeenCalledOnceWith(warning); + expect(log).toEqual('OK'); + }); + }); + it('should return ddo with reasonable defaults', function() { angular.module('my', []).component('myComponent', {}); module('my');