fix($compile): reference correct directive name in ctreq error

Previously, ctreq would possibly reference the incorrect directive name,
due to relying on a directiveName living outside of the closure which
throws the exception, which can change before the call is ever made.

This change saves the current value of directiveName as a property of
the link function, which prevents this from occurring.

Closes #7062
Closes #7067
This commit is contained in:
Caitlin Potter
2014-04-09 20:44:59 -04:00
parent fcdac65aed
commit 6bea059109
2 changed files with 27 additions and 4 deletions

View File

@@ -1341,6 +1341,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (pre) {
if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
pre.require = directive.require;
pre.directiveName = directiveName;
if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
pre = cloneAndAnnotateFn(pre, {isolateScope: true});
}
@@ -1349,6 +1350,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (post) {
if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
post.require = directive.require;
post.directiveName = directiveName;
if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
post = cloneAndAnnotateFn(post, {isolateScope: true});
}
@@ -1357,7 +1359,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
function getControllers(require, $element, elementControllers) {
function getControllers(directiveName, require, $element, elementControllers) {
var value, retrievalMethod = 'data', optional = false;
if (isString(require)) {
while((value = require.charAt(0)) == '^' || value == '?') {
@@ -1383,7 +1385,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
} else if (isArray(require)) {
value = [];
forEach(require, function(require) {
value.push(getControllers(require, $element, elementControllers));
value.push(getControllers(directiveName, require, $element, elementControllers));
});
}
return value;
@@ -1526,7 +1528,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
try {
linkFn = preLinkFns[i];
linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
} catch (e) {
$exceptionHandler(e, startingTag($element));
}
@@ -1546,7 +1548,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
try {
linkFn = postLinkFns[i];
linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);
} catch (e) {
$exceptionHandler(e, startingTag($element));
}

View File

@@ -3498,6 +3498,27 @@ describe('$compile', function() {
expect(element.text()).toBe('Hello');
});
});
it('should throw ctreq with correct directive name, regardless of order', function() {
module(function($compileProvider) {
$compileProvider.directive('aDir', valueFn({
restrict: "E",
require: "ngModel",
link: noop
}));
});
inject(function($compile, $rootScope) {
expect(function() {
// a-dir will cause a ctreq error to be thrown. Previously, the error would reference
// the last directive in the chain (which in this case would be ngClick), based on
// priority and alphabetical ordering. This test verifies that the ordering does not
// affect which directive is referenced in the minErr message.
element = $compile('<a-dir ng-click="foo=bar"></a-dir>')($rootScope);
}).toThrowMinErr('$compile', 'ctreq',
"Controller 'ngModel', required by directive 'aDir', can't be found!");
});
});
});