diff --git a/src/ng/compile.js b/src/ng/compile.js index 7d0bb008db21..a6bcc3e754ae 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1400,7 +1400,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { optional = (match[2] == '?'), mode = match[1], // @, =, or & lastValue, - parentGet, parentSet; + parentGet, parentSet, compare; isolateScope.$$isolateBindings[scopeName] = mode + attrName; @@ -1423,6 +1423,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return; } parentGet = $parse(attrs[attrName]); + if (parentGet.literal) { + compare = equals; + } else { + compare = function(a,b) { return a === b; }; + } parentSet = parentGet.assign || function() { // reset the change, or we will throw this exception on every $digest lastValue = isolateScope[scopeName] = parentGet(scope); @@ -1433,10 +1438,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { lastValue = isolateScope[scopeName] = parentGet(scope); isolateScope.$watch(function parentValueWatch() { var parentValue = parentGet(scope); - - if (parentValue !== isolateScope[scopeName]) { + if (!compare(parentValue, isolateScope[scopeName])) { // we are out of sync and need to copy - if (parentValue !== lastValue) { + if (!compare(parentValue, lastValue)) { // parent changed and it has precedence isolateScope[scopeName] = parentValue; } else { @@ -1445,7 +1449,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } } return lastValue = parentValue; - }); + }, null, parentGet.literal); break; case '&': diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index f2fa4ef66863..853290a637ba 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -2492,6 +2492,62 @@ describe('$compile', function() { expect(lastRefValueInParent).toBe('new'); })); + + describe('literal objects', function() { + it('should copy parent changes', inject(function() { + compile('
'); + + $rootScope.name = 'a'; + $rootScope.$apply(); + expect(componentScope.reference).toEqual({name: 'a'}); + + $rootScope.name = 'b'; + $rootScope.$apply(); + expect(componentScope.reference).toEqual({name: 'b'}); + })); + + it('should not change the component when parent does not change', inject(function() { + compile('
'); + + $rootScope.name = 'a'; + $rootScope.$apply(); + var lastComponentValue = componentScope.reference; + $rootScope.$apply(); + expect(componentScope.reference).toBe(lastComponentValue); + })); + + it('should complain when the component changes', inject(function() { + compile('
'); + + $rootScope.name = 'a'; + $rootScope.$apply(); + componentScope.reference = {name: 'b'}; + expect(function() { + $rootScope.$apply(); + }).toThrowMinErr("$compile", "nonassign", "Expression '{name: name}' used with directive 'myComponent' is non-assignable!"); + + })); + + it('should work for primitive literals', inject(function() { + test('1', 1); + test('null', null); + test('undefined', undefined); + test("'someString'", 'someString'); + + + function test(literalString, literalValue) { + compile('
'); + + $rootScope.$apply(); + expect(componentScope.reference).toBe(literalValue); + dealoc(element); + + } + + })); + + }); + });