diff --git a/src/ng/parse.js b/src/ng/parse.js index 5af52f600d6f..f3d9d95d8b51 100644 --- a/src/ng/parse.js +++ b/src/ng/parse.js @@ -705,6 +705,22 @@ function parser(text, json, $filter, csp){ // Parser helper functions ////////////////////////////////////////////////// +/** + * Unwrap values from a promise + * @param {Object} obj object to unwrap + * @returns if passed a promise, the inner value. Otherwise original object. + */ +function unwrapPromise(obj){ + + // If we'v been passed a promise then unwrap it. + // If the value has not been resolved yet, bind to a throwaway object. This will simulate a read-only field. + if(obj && obj.then) + return obj.$$v || {} + else + return obj; +} + + function setter(obj, path, setValue) { var element = path.split('.'); for (var i = 0; element.length > 1; i++) { @@ -714,7 +730,7 @@ function setter(obj, path, setValue) { propertyObj = {}; obj[key] = propertyObj; } - obj = propertyObj; + obj = unwrapPromise( propertyObj ); } obj[element.shift()] = setValue; return setValue; diff --git a/test/ng/parseSpec.js b/test/ng/parseSpec.js index c3cb0ce11f4a..ec133289d2b1 100644 --- a/test/ng/parseSpec.js +++ b/test/ng/parseSpec.js @@ -679,6 +679,51 @@ describe('parser', function() { expect(scope.$eval('greeting')).toBe('hello!'); }); + it('should evaluate a resolved object promise and set its value', inject(function($parse) { + var person = {'name': 'Bill Gates'}; + + deferred.resolve(person); + scope.person = promise; + + var getter = $parse( 'person.name' ); + + expect(getter(scope)).toBe(undefined); + scope.$digest(); + expect(getter(scope)).toBe('Bill Gates'); + + getter.assign(scope, 'Warren Buffet'); + expect(getter(scope)).toBe('Warren Buffet'); + })); + + it('should evaluate a resolved primitive type promise and set its value', inject(function($parse) { + deferred.resolve("Salut!"); + scope.greeting = promise; + + var getter = $parse( 'greeting' ); + + expect(getter(scope)).toBe(undefined); + scope.$digest(); + expect(getter(scope)).toBe('Salut!'); + + getter.assign(scope, 'Bonjour'); + expect(getter(scope)).toBe('Bonjour'); + })); + + it('should evaluate an unresolved promise and *not* set its value', inject(function($parse) { + + + scope.person = promise; + + var getter = $parse( 'person.name' ); + + expect(getter(scope)).toBe(undefined); + scope.$digest(); + expect(getter(scope)).toBe(undefined); + + getter.assign(scope, 'Warren Buffet'); + expect(getter(scope)).toBe(undefined); + })); + it('should evaluated rejected promise and ignore the rejection reason', function() { deferred.reject('sorry');