Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit e40345e

Browse files
committed
perf($compile): add a flag to compile only EA directives
1 parent 3a40bd4 commit e40345e

File tree

3 files changed

+166
-8
lines changed

3 files changed

+166
-8
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@ngdoc error
2+
@name $compile:rstrto
3+
@fullName Invalid restrictDirectivesTo argument value
4+
@description
5+
6+
This error occurs when you do not include `'E'` or `'A'` in the argument of {@link ng.$compileProvider#restrictDirectivesTo `$compileProvider.restrictDirectivesTo`}.
7+
8+
These values are mandatory and you must include both in the argument string.

src/ng/compile.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,42 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
13861386
return TTL;
13871387
};
13881388

1389+
var ignoreCDirectives = false;
1390+
var ignoreMDirectives = false;
1391+
/**
1392+
* @ngdoc method
1393+
* @name $compileProvider#restrictDirectivesTo
1394+
* @description
1395+
*
1396+
* It indicates to the compiler which restrict directive values
1397+
* must follow and which restrict directive values may ignore.
1398+
*
1399+
* It allows to the compiler to make optimizations, for example,
1400+
* if you indicate that you restrict directives only to ‘EA’
1401+
* (entities and attributes), it will not parse classes or comments
1402+
* looking for directives.
1403+
*
1404+
* Possible values are ‘EA’, ‘EAC’, ‘EAM’ and ‘EACM’.
1405+
* Having at least 'EA' is mandatory.
1406+
*
1407+
* Default value is ‘EACM’
1408+
*
1409+
* Example:
1410+
*
1411+
* ```
1412+
* $compileProvider.restrictDirectivesTo('EA');
1413+
* ```
1414+
*
1415+
* @param {string} directive restrict values that compiler must follow
1416+
*/
1417+
this.restrictDirectivesTo = function(value) {
1418+
if (value.indexOf('E') === -1 || value.indexOf('A') === -1) {
1419+
throw $compileMinErr('rstrto', '"{0}" must include E and A');
1420+
}
1421+
ignoreCDirectives = value.indexOf('C') === -1;
1422+
ignoreMDirectives = value.indexOf('M') === -1;
1423+
};
1424+
13891425
this.$get = [
13901426
'$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
13911427
'$controller', '$rootScope', '$sce', '$animate', '$$sanitizeUri',
@@ -2026,6 +2062,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
20262062
}
20272063

20282064
// use class as directive
2065+
if (ignoreCDirectives) break;
20292066
className = node.className;
20302067
if (isObject(className)) {
20312068
// Maybe SVGAnimatedString
@@ -2052,6 +2089,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
20522089
addTextInterpolateDirective(directives, node.nodeValue);
20532090
break;
20542091
case NODE_TYPE_COMMENT: /* Comment */
2092+
if (ignoreMDirectives) break;
20552093
collectCommentDirectives();
20562094
break;
20572095
}

test/ng/compileSpec.js

Lines changed: 120 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3128,17 +3128,129 @@ describe('$compile', function() {
31283128
});
31293129
});
31303130

3131-
it('should observe interpolated attrs', inject(function($rootScope, $compile) {
3132-
$compile('<div some-attr="{{value}}" observer></div>')($rootScope);
3131+
describe('$compileProvider.restrictDirectivesTo', function() {
31333132

3134-
// should be async
3135-
expect(observeSpy).not.toHaveBeenCalled();
3133+
var collected;
3134+
beforeEach(module(function($compileProvider) {
3135+
collected = false;
3136+
$compileProvider.directive('testCollect', function() {
3137+
return {
3138+
restrict: 'ECMA',
3139+
link: function(scope, element) {
3140+
collected = true;
3141+
}
3142+
};
3143+
});
3144+
}));
31363145

3137-
$rootScope.$apply(function() {
3138-
$rootScope.value = 'bound-value';
3146+
describe('EA', function() {
3147+
3148+
beforeEach(module(function($compileProvider) {
3149+
$compileProvider.restrictDirectivesTo('EA');
3150+
}));
3151+
3152+
var $compile, $rootScope;
3153+
beforeEach(inject(function(_$compile_,_$rootScope_) {
3154+
$compile = _$compile_;
3155+
$rootScope = _$rootScope_;
3156+
}));
3157+
3158+
it('should not compile class directives', function() {
3159+
var html = 'Classes collected: <span class="ng-bind: \'Yes\';">No</span>';
3160+
element = $compile('<div>' + html + '</div>')($rootScope);
3161+
$rootScope.$apply();
3162+
expect(element.text()).toBe('Classes collected: No');
3163+
});
3164+
3165+
it('should not compile comment directives', function() {
3166+
var html = '<!-- directive: test-collect -->';
3167+
element = $compile('<div>' + html + '</div>')($rootScope);
3168+
expect(collected).toBe(false);
3169+
});
3170+
3171+
it('should not prevent to compile entity directives', function() {
3172+
element = $compile('<test-collect></test-collect>')($rootScope);
3173+
expect(collected).toBe(true);
3174+
});
3175+
3176+
it('should not prevent to compile attribute directives', function() {
3177+
element = $compile('<span test-collect></span>')($rootScope);
3178+
expect(collected).toBe(true);
3179+
});
3180+
3181+
it('should not prevent to compile interpolated expressions', function() {
3182+
element = $compile('<span>{{"text "+"interpolated"}}</span>')($rootScope);
3183+
$rootScope.$apply();
3184+
expect(element.text()).toBe('text interpolated');
3185+
});
3186+
3187+
it('should interpolate expressions inside class attribute', function() {
3188+
$rootScope.interpolateMe = 'interpolated';
3189+
var html = '<div class="{{interpolateMe}}"></div>';
3190+
element = $compile(html)($rootScope);
3191+
$rootScope.$apply();
3192+
expect(element).toHaveClass('interpolated');
3193+
});
31393194
});
3140-
expect(observeSpy).toHaveBeenCalledOnceWith('bound-value');
3141-
}));
3195+
3196+
describe('EAC', function() {
3197+
3198+
beforeEach(module(function($compileProvider) {
3199+
$compileProvider.restrictDirectivesTo('EAC');
3200+
}));
3201+
3202+
var $compile, $rootScope;
3203+
beforeEach(inject(function(_$compile_,_$rootScope_) {
3204+
$compile = _$compile_;
3205+
$rootScope = _$rootScope_;
3206+
}));
3207+
3208+
it('should compile class directives', function() {
3209+
var html = 'Classes collected: <span class="ng-bind: \'Yes\';">No</span>';
3210+
element = $compile('<div>' + html + '</div>')($rootScope);
3211+
$rootScope.$apply();
3212+
expect(element.text()).toBe('Classes collected: Yes');
3213+
});
3214+
});
3215+
3216+
describe('EAM', function() {
3217+
3218+
beforeEach(module(function($compileProvider) {
3219+
$compileProvider.restrictDirectivesTo('EAM');
3220+
}));
3221+
3222+
var $compile, $rootScope;
3223+
beforeEach(inject(function(_$compile_,_$rootScope_) {
3224+
$compile = _$compile_;
3225+
$rootScope = _$rootScope_;
3226+
}));
3227+
3228+
it('should compile comment directives', function() {
3229+
var html = '<!-- directive: test-collect -->';
3230+
element = $compile('<div>' + html + '</div>')($rootScope);
3231+
expect(collected).toBe(true);
3232+
});
3233+
});
3234+
3235+
describe('without E or A', function() {
3236+
3237+
it('should throw an exception if E is not included', module(function($compileProvider) {
3238+
expect(function() {
3239+
$compileProvider.restrictDirectivesTo('A');
3240+
}).toThrowMinErr('$compile', 'rstrto');
3241+
}));
3242+
3243+
it('should throw an exception if A is not included', module(function($compileProvider) {
3244+
expect(function() {
3245+
$compileProvider.restrictDirectivesTo('E');
3246+
}).toThrowMinErr('$compile', 'rstrto');
3247+
}));
3248+
3249+
afterEach(inject(function($compile) {
3250+
// ensure that $compileProvider is instantiated
3251+
}));
3252+
});
3253+
});
31423254

31433255

31443256
it('should return a deregistration function while observing an attribute', inject(function($rootScope, $compile) {

0 commit comments

Comments
 (0)