fix($parse): Preserve expensive checks when runnning $eval inside an …
…expression When running an expression with expensive checks, there is a call to `$eval` or `$evalAsync` then that expression is also evaluated using expensive checks Closes: #13850
- Loading branch information
- +37 −2 src/ng/parse.js
- +2 −1 src/ng/rootScope.js
- +77 −1 test/ng/parseSpec.js
- +4 −4 test/ng/rootScopeSpec.js
| @@ -1757,10 +1757,19 @@ function $ParseProvider() { | ||
| csp: noUnsafeEval, | ||
| expensiveChecks: true | ||
| }; | ||
| var runningChecksEnabled = false; | ||
|
|
||
| return function $parse(exp, interceptorFn, expensiveChecks) { | ||
| $parse.$$runningExpensiveChecks = function() { | ||
| return runningChecksEnabled; | ||
| }; | ||
|
|
||
| return $parse; | ||
|
|
||
| function $parse(exp, interceptorFn, expensiveChecks) { | ||
| var parsedExpression, oneTime, cacheKey; | ||
|
|
||
| expensiveChecks = expensiveChecks || runningChecksEnabled; | ||
|
|
||
| switch (typeof exp) { | ||
| case 'string': | ||
| exp = exp.trim(); | ||
| @@ -1786,6 +1795,9 @@ function $ParseProvider() { | ||
| } else if (parsedExpression.inputs) { | ||
| parsedExpression.$$watchDelegate = inputsWatchDelegate; | ||
| } | ||
| if (expensiveChecks) { | ||
| parsedExpression = expensiveChecksInterceptor(parsedExpression); | ||
| } | ||
| cache[cacheKey] = parsedExpression; | ||
| } | ||
| return addInterceptor(parsedExpression, interceptorFn); | ||
| @@ -1796,7 +1808,30 @@ function $ParseProvider() { | ||
| default: | ||
| return addInterceptor(noop, interceptorFn); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| function expensiveChecksInterceptor(fn) { | ||
| if (!fn) return fn; | ||
| expensiveCheckFn.$$watchDelegate = fn.$$watchDelegate; | ||
| expensiveCheckFn.assign = expensiveChecksInterceptor(fn.assign); | ||
This comment has been minimized.
This comment has been minimized.
lgalfaso
Author
Member
|
||
| expensiveCheckFn.constant = fn.constant; | ||
| expensiveCheckFn.literal = fn.literal; | ||
| for (var i = 0; fn.inputs && i < fn.inputs.length; ++i) { | ||
| fn.inputs[i] = expensiveChecksInterceptor(fn.inputs[i]); | ||
This comment has been minimized.
gkalpak
Member
|
||
| } | ||
|
|
||
| return expensiveCheckFn; | ||
|
|
||
| function expensiveCheckFn(scope, locals, assign, inputs) { | ||
| var expensiveCheckOldValue = runningChecksEnabled; | ||
| runningChecksEnabled = true; | ||
| try { | ||
| return fn(scope, locals, assign, inputs); | ||
| } finally { | ||
| runningChecksEnabled = expensiveCheckOldValue; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| function expressionInputDirtyCheck(newValue, oldValueOfValue) { | ||
|
|
||
Do we really need to pass
fn.assignthroughexpesiveChecksInterceptor()?Isn't the function already created based on
expensiveChecks?