diff --git a/src/ng/compile.js b/src/ng/compile.js index 63eb52fcb77f..a651777a222c 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -794,7 +794,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { $observe: function(key, fn) { var attrs = this, $$observers = (attrs.$$observers || (attrs.$$observers = {})), - listeners = ($$observers[key] || ($$observers[key] = [])); + listeners = (($$observers.hasOwnProperty(key) && isArray($$observers[key]) && + $$observers[key]) || ($$observers[key] = [])); listeners.push(fn); $rootScope.$evalAsync(function() { diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 992d7edc51e1..da2d17d9d068 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -2693,6 +2693,34 @@ describe('$compile', function() { })); + it('should be able to bind attribute names which are present in Object.prototype', function() { + module(function() { + directive('inProtoAttr', valueFn({ + scope: { + 'constructor': '@', + // Spidermonkey extension, may be obsolete in the future + 'watch': '=', + 'unwatch': '&' + } + })); + }); + inject(function($rootScope) { + expect(function() { + compile('
'); + }).not.toThrow(); + var isolateScope = element.isolateScope(); + + expect(typeof isolateScope.constructor).toBe('string'); + expect(isArray(isolateScope.watch)).toBe(true); + expect(typeof isolateScope.unwatch).toBe('function'); + expect($rootScope.value).toBeUndefined(); + isolateScope.unwatch(); + expect($rootScope.value).toBe(true); + }); + }); + + describe('attribute', function() { it('should copy simple attribute', inject(function() { compile('