diff --git a/src/ng/parse.js b/src/ng/parse.js index 68c832b8..09b751d3 100644 --- a/src/ng/parse.js +++ b/src/ng/parse.js @@ -362,6 +362,8 @@ Parser.prototype = { primary = this.arrayDeclaration(); } else if (this.expect('{')) { primary = this.object(); + } else if (this.peek().identifier && this.peek().text in CONSTANTS) { + primary = CONSTANTS[this.consume().text]; } else if (this.peek().identifier) { primary = this.identifier(); } else if (this.peek().constant) { @@ -464,7 +466,7 @@ Parser.prototype = { id += this.consume().text + this.consume().text; } - return CONSTANTS[id] || getterFn(id, this.options, this.text); + return getterFn(id, this.options, this.text); }, constant: function() { @@ -654,17 +656,16 @@ Parser.prototype = { }, fieldAccess: function(object) { - var expression = this.text; - var field = this.consume().text; - var getter = getterFn(field, this.options, expression); + var getter = this.identifier(); return extend(function $parseFieldAccess(scope, locals, self) { - return getter(self || object(scope, locals)); + var o = self || object(scope, locals); + return (o == null) ? undefined : getter(o); }, { assign: function(scope, value, locals) { var o = object(scope, locals); if (!o) object.assign(scope, o = {}); - return setter(o, field, value, expression); + return getter.assign(o, value); } }); }, diff --git a/test/ng/parseSpec.js b/test/ng/parseSpec.js index dfe5de69..9ad86559 100644 --- a/test/ng/parseSpec.js +++ b/test/ng/parseSpec.js @@ -771,7 +771,7 @@ describe('parser', function() { scope.$eval('{}.toString.constructor.a = 1'); }).toThrowMinErr( '$parse', 'isecfn','Referencing Function in Angular expressions is disallowed! ' + - 'Expression: {}.toString.constructor.a = 1'); + 'Expression: toString.constructor.a'); expect(function() { scope.$eval('{}.toString["constructor"]["constructor"] = 1'); @@ -1835,6 +1835,19 @@ describe('parser', function() { $rootScope.fn = function() {}; expect($rootScope.$eval('foo + "bar" + fn()')).toBe('bar'); })); + + it('should treat properties named null/undefined as normal properties', inject(function($rootScope) { + expect($rootScope.$eval("a.null.undefined.b", {a:{null:{undefined:{b: 1}}}})).toBe(1); + })); + + it('should not allow overriding null/undefined keywords', inject(function($rootScope) { + expect($rootScope.$eval('null.a', {null: {a: 42}})).toBeUndefined(); + })); + + it('should allow accessing null/undefined properties on `this`', inject(function($rootScope) { + $rootScope.null = {a: 42}; + expect($rootScope.$eval('this.null.a')).toBe(42); + })); }); }); });