Permalink
Browse files

fix($parse): remove deprecated promise unwrapping

The feature has been deprecated in #4317

BREAKING CHANGE: promise unwrapping has been removed.
It has been deprecated since 1.2.0-rc.3.

It can no longer be turned on.
Two methods have been removed:
* $parseProvider.unwrapPromises
* $parseProvider.logPromiseWarnings
  • Loading branch information...
1 parent 3f365f5 commit fa6e411da26824a5bae55f37ce7dbb859653276d @rodyhaddad rodyhaddad committed May 22, 2014
Showing with 781 additions and 1,373 deletions.
  1. +24 −220 src/ng/parse.js
  2. +757 −1,153 test/ng/parseSpec.js
View
@@ -1,8 +1,6 @@
'use strict';
var $parseMinErr = minErr('$parse');
-var promiseWarningCache = {};
-var promiseWarning;
// Sandboxing Angular Expressions
// ------------------------------
@@ -700,14 +698,6 @@ Parser.prototype = {
if (!o) return undefined;
v = ensureSafeObject(o[i], parser.text);
- if (v && v.then && parser.options.unwrapPromises) {
- p = v;
- if (!('$$v' in v)) {
- p.$$v = undefined;
- p.then(function(val) { p.$$v = val; });
- }
- v = v.$$v;
- }
return v;
}, {
assign: function(self, value, locals) {
@@ -835,18 +825,6 @@ function setter(obj, path, setValue, fullExp, options) {
obj[key] = propertyObj;
}
obj = propertyObj;
- if (obj.then && options.unwrapPromises) {
- promiseWarning(fullExp);
- if (!("$$v" in obj)) {
- (function(promise) {
- promise.then(function(val) { promise.$$v = val; }); }
- )(obj);
- }
- if (obj.$$v === undefined) {
- obj.$$v = {};
- }
- obj = obj.$$v;
- }
}
key = ensureSafeMemberName(element.shift(), fullExp);
obj[key] = setValue;
@@ -867,101 +845,30 @@ function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
ensureSafeMemberName(key3, fullExp);
ensureSafeMemberName(key4, fullExp);
- return !options.unwrapPromises
- ? function cspSafeGetter(scope, locals) {
- var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
-
- if (pathVal == null) return pathVal;
- pathVal = pathVal[key0];
+ return function cspSafeGetter(scope, locals) {
+ var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
- if (!key1) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key1];
+ if (pathVal == null) return pathVal;
+ pathVal = pathVal[key0];
- if (!key2) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key2];
+ if (!key1) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = pathVal[key1];
- if (!key3) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key3];
+ if (!key2) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = pathVal[key2];
- if (!key4) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key4];
+ if (!key3) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = pathVal[key3];
- return pathVal;
- }
- : function cspSafePromiseEnabledGetter(scope, locals) {
- var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
- promise;
-
- if (pathVal == null) return pathVal;
-
- pathVal = pathVal[key0];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
+ if (!key4) return pathVal;
+ if (pathVal == null) return undefined;
+ pathVal = pathVal[key4];
- if (!key1) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key1];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
-
- if (!key2) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key2];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
-
- if (!key3) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key3];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
-
- if (!key4) return pathVal;
- if (pathVal == null) return undefined;
- pathVal = pathVal[key4];
- if (pathVal && pathVal.then) {
- promiseWarning(fullExp);
- if (!("$$v" in pathVal)) {
- promise = pathVal;
- promise.$$v = undefined;
- promise.then(function(val) { promise.$$v = val; });
- }
- pathVal = pathVal.$$v;
- }
- return pathVal;
- };
+ return pathVal;
+ };
}
function simpleGetterFn1(key0, fullExp) {
@@ -998,9 +905,9 @@ function getterFn(path, options, fullExp) {
// When we have only 1 or 2 tokens, use optimized special case closures.
// http://jsperf.com/angularjs-parse-getter/6
- if (!options.unwrapPromises && pathKeysLength === 1) {
+ if (pathKeysLength === 1) {
fn = simpleGetterFn1(pathKeys[0], fullExp);
- } else if (!options.unwrapPromises && pathKeysLength === 2) {
+ } else if (pathKeysLength === 2) {
fn = simpleGetterFn2(pathKeys[0], pathKeys[1], fullExp);
} else if (options.csp) {
if (pathKeysLength < 6) {
@@ -1028,28 +935,15 @@ function getterFn(path, options, fullExp) {
// we simply dereference 's' on any .dot notation
? 's'
// but if we are first then we check locals first, and if so read it first
- : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' +
- (options.unwrapPromises
- ? 'if (s && s.then) {\n' +
- ' pw("' + fullExp.replace(/(["\r\n])/g, '\\$1') + '");\n' +
- ' if (!("$$v" in s)) {\n' +
- ' p=s;\n' +
- ' p.$$v = undefined;\n' +
- ' p.then(function(v) {p.$$v=v;});\n' +
- '}\n' +
- ' s=s.$$v\n' +
- '}\n'
- : '');
+ : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n';
});
code += 'return s;';
/* jshint -W054 */
- var evaledFnGetter = new Function('s', 'k', 'pw', code); // s=scope, k=locals, pw=promiseWarning
+ var evaledFnGetter = new Function('s', 'k', code); // s=scope, k=locals
/* jshint +W054 */
evaledFnGetter.toString = valueFn(code);
- fn = options.unwrapPromises ? function(scope, locals) {
- return evaledFnGetter(scope, locals, promiseWarning);
- } : evaledFnGetter;
+ fn = evaledFnGetter;
}
// Only cache the value if it's not going to mess up the cache object
@@ -1116,103 +1010,13 @@ function $ParseProvider() {
var cache = {};
var $parseOptions = {
- csp: false,
- unwrapPromises: false,
- logPromiseWarnings: true
- };
-
-
- /**
- * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
- *
- * @ngdoc method
- * @name $parseProvider#unwrapPromises
- * @description
- *
- * **This feature is deprecated, see deprecation notes below for more info**
- *
- * If set to true (default is false), $parse will unwrap promises automatically when a promise is
- * found at any part of the expression. In other words, if set to true, the expression will always
- * result in a non-promise value.
- *
- * While the promise is unresolved, it's treated as undefined, but once resolved and fulfilled,
- * the fulfillment value is used in place of the promise while evaluating the expression.
- *
- * **Deprecation notice**
- *
- * This is a feature that didn't prove to be wildly useful or popular, primarily because of the
- * dichotomy between data access in templates (accessed as raw values) and controller code
- * (accessed as promises).
- *
- * In most code we ended up resolving promises manually in controllers anyway and thus unifying
- * the model access there.
- *
- * Other downsides of automatic promise unwrapping:
- *
- * - when building components it's often desirable to receive the raw promises
- * - adds complexity and slows down expression evaluation
- * - makes expression code pre-generation unattractive due to the amount of code that needs to be
- * generated
- * - makes IDE auto-completion and tool support hard
- *
- * **Warning Logs**
- *
- * If the unwrapping is enabled, Angular will log a warning about each expression that unwraps a
- * promise (to reduce the noise, each expression is logged only once). To disable this logging use
- * `$parseProvider.logPromiseWarnings(false)` api.
- *
- *
- * @param {boolean=} value New value.
- * @returns {boolean|self} Returns the current setting when used as getter and self if used as
- * setter.
- */
- this.unwrapPromises = function(value) {
- if (isDefined(value)) {
- $parseOptions.unwrapPromises = !!value;
- return this;
- } else {
- return $parseOptions.unwrapPromises;
- }
- };
-
-
- /**
- * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
- *
- * @ngdoc method
- * @name $parseProvider#logPromiseWarnings
- * @description
- *
- * Controls whether Angular should log a warning on any encounter of a promise in an expression.
- *
- * The default is set to `true`.
- *
- * This setting applies only if `$parseProvider.unwrapPromises` setting is set to true as well.
- *
- * @param {boolean=} value New value.
- * @returns {boolean|self} Returns the current setting when used as getter and self if used as
- * setter.
- */
- this.logPromiseWarnings = function(value) {
- if (isDefined(value)) {
- $parseOptions.logPromiseWarnings = value;
- return this;
- } else {
- return $parseOptions.logPromiseWarnings;
- }
+ csp: false
};
this.$get = ['$filter', '$sniffer', '$log', function($filter, $sniffer, $log) {
$parseOptions.csp = $sniffer.csp;
- promiseWarning = function promiseWarningFn(fullExp) {
- if (!$parseOptions.logPromiseWarnings || promiseWarningCache.hasOwnProperty(fullExp)) return;
- promiseWarningCache[fullExp] = true;
- $log.warn('[$parse] Promise found in the expression `' + fullExp + '`. ' +
- 'Automatic unwrapping of promises in Angular expressions is deprecated.');
- };
-
return function(exp) {
var parsedExpression;
Oops, something went wrong.

0 comments on commit fa6e411

Please sign in to comment.