aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Bosch2013-12-12 15:36:16 -0800
committerTobias Bosch2013-12-12 16:30:31 -0800
commit43072e3812e32b89b97ad03144577cba50d4b776 (patch)
tree07f9f4c75ccd581d3b7ad0004c07f07dda5bd8b6
parent9396d55414ef41ec3a109eefcf6c65dc00b446c4 (diff)
downloadangular.js-43072e3812e32b89b97ad03144577cba50d4b776.tar.bz2
fix($compile): Allow literals in isolate scope references
When a component uses an isolate scope reference and the the component is used with an object literal a new object is created on every evaluation. Therefore the compiler needs to compare the values of the parent and the isolate scope using object equality and not object reference equality. Fixes #5296.
-rw-r--r--src/ng/compile.js14
-rwxr-xr-xtest/ng/compileSpec.js56
2 files changed, 65 insertions, 5 deletions
diff --git a/src/ng/compile.js b/src/ng/compile.js
index 7d0bb008..a6bcc3e7 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 f2fa4ef6..853290a6 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('<div><span my-component reference="{name: name}">');
+
+ $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('<div><span my-component reference="{name: name}">');
+
+ $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('<div><span my-component reference="{name: name}">');
+
+ $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('<div><span my-component reference="'+literalString+'">');
+
+ $rootScope.$apply();
+ expect(componentScope.reference).toBe(literalValue);
+ dealoc(element);
+
+ }
+
+ }));
+
+ });
+
});