mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-04-08 22:37:20 +08:00
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
This commit is contained in:
244
src/ng/parse.js
244
src/ng/parse.js
@@ -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;
|
||||
return function cspSafeGetter(scope, locals) {
|
||||
var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
|
||||
|
||||
if (pathVal == null) return pathVal;
|
||||
pathVal = pathVal[key0];
|
||||
if (pathVal == null) return pathVal;
|
||||
pathVal = pathVal[key0];
|
||||
|
||||
if (!key1) return pathVal;
|
||||
if (pathVal == null) return undefined;
|
||||
pathVal = pathVal[key1];
|
||||
if (!key1) return pathVal;
|
||||
if (pathVal == null) return undefined;
|
||||
pathVal = pathVal[key1];
|
||||
|
||||
if (!key2) return pathVal;
|
||||
if (pathVal == null) return undefined;
|
||||
pathVal = pathVal[key2];
|
||||
if (!key2) return pathVal;
|
||||
if (pathVal == null) return undefined;
|
||||
pathVal = pathVal[key2];
|
||||
|
||||
if (!key3) return pathVal;
|
||||
if (pathVal == null) return undefined;
|
||||
pathVal = pathVal[key3];
|
||||
if (!key3) return pathVal;
|
||||
if (pathVal == null) return undefined;
|
||||
pathVal = pathVal[key3];
|
||||
|
||||
if (!key4) return pathVal;
|
||||
if (pathVal == null) return undefined;
|
||||
pathVal = pathVal[key4];
|
||||
if (!key4) return pathVal;
|
||||
if (pathVal == null) return undefined;
|
||||
pathVal = pathVal[key4];
|
||||
|
||||
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 (!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;
|
||||
|
||||
|
||||
2112
test/ng/parseSpec.js
2112
test/ng/parseSpec.js
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user