Skip to content

Commit 0305753

Browse files
committed
fix(parse): Fix context access and double function call
Fix a context duplication and invocation to a previous context when doing an access modifier function on the result of a function Closes angular#2496
1 parent 2629f7f commit 0305753

File tree

2 files changed

+107
-12
lines changed

2 files changed

+107
-12
lines changed

src/ng/parse.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,8 @@ function parser(text, json, $filter, csp){
438438
text.substring(0, token.index) + "] can not be assigned to", token);
439439
}
440440
right = logicalOR();
441-
return function(self, locals){
442-
return left.assign(self, right(self, locals), locals);
441+
return function(scope, locals){
442+
return left.assign(scope, right(scope, locals), locals);
443443
};
444444
} else {
445445
return left;
@@ -559,12 +559,12 @@ function parser(text, json, $filter, csp){
559559
var field = expect().text;
560560
var getter = getterFn(field, csp);
561561
return extend(
562-
function(self, locals) {
563-
return getter(object(self, locals), locals);
562+
function(scope, locals, self) {
563+
return getter(self || object(scope, locals), locals);
564564
},
565565
{
566-
assign:function(self, value, locals) {
567-
return setter(object(self, locals), field, value);
566+
assign:function(scope, value, locals) {
567+
return setter(object(scope, locals), field, value);
568568
}
569569
}
570570
);
@@ -605,14 +605,14 @@ function parser(text, json, $filter, csp){
605605
} while (expect(','));
606606
}
607607
consume(')');
608-
return function(self, locals){
608+
return function(scope, locals){
609609
var args = [],
610-
context = contextGetter ? contextGetter(self, locals) : self;
610+
context = contextGetter ? contextGetter(scope, locals) : scope;
611611

612612
for ( var i = 0; i < argsFn.length; i++) {
613-
args.push(argsFn[i](self, locals));
613+
args.push(argsFn[i](scope, locals));
614614
}
615-
var fnPtr = fn(self, locals) || noop;
615+
var fnPtr = fn(scope, locals, context) || noop;
616616
// IE stupidity!
617617
return fnPtr.apply
618618
? fnPtr.apply(context, args)

test/ng/parseSpec.js

+97-2
Original file line numberDiff line numberDiff line change
@@ -483,13 +483,108 @@ describe('parser', function() {
483483
});
484484

485485

486+
it('should call the function from the received instance and not from a new one', function() {
487+
var n = 0;
488+
scope.fn = function() {
489+
var c = n++;
490+
return { c: c, anotherFn: function() { return this.c == c; } };
491+
};
492+
expect(scope.$eval('fn().anotherFn()')).toBe(true);
493+
});
494+
495+
486496
it('should call the function once when it is part of the context', function() {
487497
var count = 0;
488498
scope.fn = function() {
489499
count++;
500+
return { anotherFn: function() { return "lucas"; } };
501+
};
502+
expect(scope.$eval('fn().anotherFn()')).toBe('lucas');
503+
expect(count).toBe(1);
504+
});
505+
506+
507+
it('should call the function once when it is not part of the context', function() {
508+
var count = 0;
509+
scope.fn = function() {
510+
count++;
511+
return function() { return 'lucas'; };
512+
};
513+
expect(scope.$eval('fn()()')).toBe('lucas');
514+
expect(count).toBe(1);
515+
});
516+
517+
518+
it('should call the function once when it is not part of the context', function() {
519+
var count = 0;
520+
scope.fn = function() {
521+
count++;
522+
return function() { return 'lucas'; };
523+
};
524+
expect(scope.$eval('fn()()')).toBe('lucas');
525+
expect(count).toBe(1);
526+
});
527+
528+
529+
it('should call the function once when it is part of the context on assignments', function() {
530+
var count = 0;
531+
var element = {};
532+
scope.fn = function() {
533+
count++;
534+
return element;
535+
};
536+
expect(scope.$eval('fn().name = "lucas"')).toBe('lucas');
537+
expect(element.name).toBe('lucas');
538+
expect(count).toBe(1);
539+
});
540+
541+
542+
it('should call the function once when it is part of the context on array lookups', function() {
543+
var count = 0;
544+
var element = [];
545+
scope.fn = function() {
546+
count++;
547+
return element;
548+
};
549+
expect(scope.$eval('fn()[0] = "lucas"')).toBe('lucas');
550+
expect(element[0]).toBe('lucas');
551+
expect(count).toBe(1);
552+
});
553+
554+
555+
it('should call the function once when it is part of the context on array lookup function', function() {
556+
var count = 0;
557+
var element = [{anotherFn: function() { return 'lucas';} }];
558+
scope.fn = function() {
559+
count++;
560+
return element;
561+
};
562+
expect(scope.$eval('fn()[0].anotherFn()')).toBe('lucas');
563+
expect(count).toBe(1);
564+
});
565+
566+
567+
it('should call the function once when it is part of the context on array lookup function', function() {
568+
var count = 0;
569+
var element = {name: {anotherFn: function() { return 'lucas';} } };
570+
scope.fn = function() {
571+
count++;
572+
return element;
573+
};
574+
expect(scope.$eval('fn().name.anotherFn()')).toBe('lucas');
575+
expect(count).toBe(1);
576+
});
577+
578+
579+
it('should call the function once when it is part of a sub-expression', function() {
580+
var count = 0;
581+
scope.element = [{}];
582+
scope.fn = function() {
583+
count++;
584+
return 0;
490585
};
491-
scope.fn.anotherFn = function() { return ''; };
492-
expect(scope.$eval('fn().anotherFn()')).toBe('');
586+
expect(scope.$eval('element[fn()].name = "lucas"')).toBe('lucas');
587+
expect(scope.element[0].name).toBe('lucas');
493588
expect(count).toBe(1);
494589
});
495590

0 commit comments

Comments
 (0)