Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 61906d3

Browse files
James Davieschirayuk
James Davies
authored andcommitted
fix($parse): unwrap promise when setting a field
This fixes an inconsistency where you can't call the setter function when the expression resolves to a top level field name on a promise. Setting a field on an unresolved promise will throw an exception. (This shouldn't really happen in your template/js code and points to a programming error.) Closes #1827
1 parent 0bbd20f commit 61906d3

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

src/ng/parse.js

+11
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,17 @@ function setter(obj, path, setValue, fullExp) {
766766
obj[key] = propertyObj;
767767
}
768768
obj = propertyObj;
769+
if (obj.then) {
770+
if (!("$$v" in obj)) {
771+
(function(promise) {
772+
promise.then(function(val) { promise.$$v = val; }); }
773+
)(obj);
774+
}
775+
if (obj.$$v === undefined) {
776+
obj.$$v = {};
777+
}
778+
obj = obj.$$v;
779+
}
769780
}
770781
key = ensureSafeMemberName(element.shift(), fullExp);
771782
obj[key] = setValue;

test/ng/parseSpec.js

+80
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,86 @@ describe('parser', function() {
845845
scope.$digest();
846846
expect(scope.$eval('greeting')).toBe(undefined);
847847
});
848+
849+
850+
describe('assignment into promises', function() {
851+
// This behavior is analogous to assignments to non-promise values
852+
// that are lazily set on the scope.
853+
it('should evaluate a resolved object promise and set its value', inject(function($parse) {
854+
scope.person = promise;
855+
deferred.resolve({'name': 'Bill Gates'});
856+
857+
var getter = $parse('person.name');
858+
expect(getter(scope)).toBe(undefined);
859+
860+
scope.$digest();
861+
expect(getter(scope)).toBe('Bill Gates');
862+
getter.assign(scope, 'Warren Buffet');
863+
expect(getter(scope)).toBe('Warren Buffet');
864+
}));
865+
866+
867+
it('should evaluate a resolved primitive type promise and set its value', inject(function($parse) {
868+
scope.greeting = promise;
869+
deferred.resolve('Salut!');
870+
871+
var getter = $parse('greeting');
872+
expect(getter(scope)).toBe(undefined);
873+
874+
scope.$digest();
875+
expect(getter(scope)).toBe('Salut!');
876+
877+
getter.assign(scope, 'Bonjour');
878+
expect(getter(scope)).toBe('Bonjour');
879+
}));
880+
881+
882+
it('should evaluate an unresolved promise and set and remember its value', inject(function($parse) {
883+
scope.person = promise;
884+
885+
var getter = $parse('person.name');
886+
expect(getter(scope)).toBe(undefined);
887+
888+
scope.$digest();
889+
expect(getter(scope)).toBe(undefined);
890+
891+
getter.assign(scope, 'Bonjour');
892+
scope.$digest();
893+
894+
expect(getter(scope)).toBe('Bonjour');
895+
896+
var c1Getter = $parse('person.A.B.C1');
897+
scope.$digest();
898+
expect(c1Getter(scope)).toBe(undefined);
899+
c1Getter.assign(scope, 'c1_value');
900+
scope.$digest();
901+
expect(c1Getter(scope)).toBe('c1_value');
902+
903+
// Set another property on the person.A.B
904+
var c2Getter = $parse('person.A.B.C2');
905+
scope.$digest();
906+
expect(c2Getter(scope)).toBe(undefined);
907+
c2Getter.assign(scope, 'c2_value');
908+
scope.$digest();
909+
expect(c2Getter(scope)).toBe('c2_value');
910+
911+
// c1 should be unchanged.
912+
expect($parse('person.A')(scope)).toEqual(
913+
{B: {C1: 'c1_value', C2: 'c2_value'}});
914+
}));
915+
916+
917+
it('should evaluate a resolved promise and overwrite the previous set value in the absense of the getter',
918+
inject(function($parse) {
919+
scope.person = promise;
920+
var c1Getter = $parse('person.A.B.C1');
921+
c1Getter.assign(scope, 'c1_value');
922+
// resolving the promise should update the tree.
923+
deferred.resolve({A: {B: {C1: 'resolved_c1'}}});
924+
scope.$digest();
925+
expect(c1Getter(scope)).toEqual('resolved_c1');
926+
}));
927+
});
848928
});
849929

850930
describe('dereferencing', function() {

0 commit comments

Comments
 (0)