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

Commit 6a38dbf

Browse files
caitppetebacondarwin
authored andcommitted
fix($compile): do not initialize optional '&' binding if attribute not specified
BREAKING CHANGE: Previously, '&' expressions would always set up a function in the isolate scope. Now, if the binding is marked as optional and the attribute is not specified, no function will be added to the isolate scope. Closes #6404 Closes #9216
1 parent 30e5b52 commit 6a38dbf

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

src/ng/compile.js

+7
Original file line numberDiff line numberDiff line change
@@ -2576,7 +2576,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
25762576
break;
25772577

25782578
case '&':
2579+
// Don't assign Object.prototype method to scope
2580+
if (!attrs.hasOwnProperty(attrName) && optional) break;
2581+
25792582
parentGet = $parse(attrs[attrName]);
2583+
2584+
// Don't assign noop to destination if expression is not valid
2585+
if (parentGet === noop && optional) break;
2586+
25802587
destination[scopeName] = function(locals) {
25812588
return parentGet(scope, locals);
25822589
};

src/ng/parse.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,7 @@ function $ParseProvider() {
10791079
return addInterceptor(exp, interceptorFn);
10801080

10811081
default:
1082-
return addInterceptor(noop, interceptorFn);
1082+
return noop;
10831083
}
10841084
};
10851085

test/ng/compileSpec.js

+35-1
Original file line numberDiff line numberDiff line change
@@ -3084,7 +3084,9 @@ describe('$compile', function() {
30843084
colref: '=*',
30853085
colrefAlias: '=* colref',
30863086
expr: '&',
3087-
exprAlias: '&expr'
3087+
optExpr: '&?',
3088+
exprAlias: '&expr',
3089+
constructor: '&?'
30883090
},
30893091
link: function(scope) {
30903092
componentScope = scope;
@@ -3224,6 +3226,38 @@ describe('$compile', function() {
32243226
});
32253227

32263228

3229+
it('should not initialize scope value if optional expression binding is not passed', inject(function($compile) {
3230+
compile('<div my-component></div>');
3231+
var isolateScope = element.isolateScope();
3232+
expect(isolateScope.optExpr).toBeUndefined();
3233+
}));
3234+
3235+
3236+
it('should not initialize scope value if optional expression binding with Object.prototype name is not passed', inject(function($compile) {
3237+
compile('<div my-component></div>');
3238+
var isolateScope = element.isolateScope();
3239+
expect(isolateScope.constructor).toBe($rootScope.constructor);
3240+
}));
3241+
3242+
3243+
it('should initialize scope value if optional expression binding is passed', inject(function($compile) {
3244+
compile('<div my-component opt-expr="value = \'did!\'"></div>');
3245+
var isolateScope = element.isolateScope();
3246+
expect(typeof isolateScope.optExpr).toBe('function');
3247+
expect(isolateScope.optExpr()).toBe('did!');
3248+
expect($rootScope.value).toBe('did!');
3249+
}));
3250+
3251+
3252+
it('should initialize scope value if optional expression binding with Object.prototype name is passed', inject(function($compile) {
3253+
compile('<div my-component constructor="value = \'did!\'"></div>');
3254+
var isolateScope = element.isolateScope();
3255+
expect(typeof isolateScope.constructor).toBe('function');
3256+
expect(isolateScope.constructor()).toBe('did!');
3257+
expect($rootScope.value).toBe('did!');
3258+
}));
3259+
3260+
32273261
describe('bind-once', function() {
32283262

32293263
function countWatches(scope) {

0 commit comments

Comments
 (0)