-
Notifications
You must be signed in to change notification settings - Fork 27.3k
perf(*): more performant interpolation and lazy one-time binding #7700
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -991,68 +991,88 @@ function $ParseProvider() { | |
| this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { | ||
| $parseOptions.csp = $sniffer.csp; | ||
|
|
||
| return function(exp) { | ||
| var parsedExpression, | ||
| oneTime; | ||
| return function(exp, interceptorFn) { | ||
| var parsedExpression, oneTime, | ||
| cacheKey = (exp = trim(exp)); | ||
|
|
||
| switch (typeof exp) { | ||
| case 'string': | ||
| if (cache.hasOwnProperty(cacheKey)) { | ||
| parsedExpression = cache[cacheKey]; | ||
| } else { | ||
| if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { | ||
| oneTime = true; | ||
| exp = exp.substring(2); | ||
| } | ||
|
|
||
| exp = trim(exp); | ||
|
|
||
| if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { | ||
| oneTime = true; | ||
| exp = exp.substring(2); | ||
| } | ||
|
|
||
| if (cache.hasOwnProperty(exp)) { | ||
| return oneTime ? oneTimeWrapper(cache[exp]) : cache[exp]; | ||
| } | ||
| var lexer = new Lexer($parseOptions); | ||
| var parser = new Parser(lexer, $filter, $parseOptions); | ||
| parsedExpression = parser.parse(exp); | ||
|
|
||
| var lexer = new Lexer($parseOptions); | ||
| var parser = new Parser(lexer, $filter, $parseOptions); | ||
| parsedExpression = parser.parse(exp); | ||
| if (parsedExpression.constant) parsedExpression.$$watchDelegate = constantWatch; | ||
| else if (oneTime) parsedExpression.$$watchDelegate = oneTimeWatch; | ||
|
|
||
| if (exp !== 'hasOwnProperty') { | ||
| // Only cache the value if it's not going to mess up the cache object | ||
| // This is more performant that using Object.prototype.hasOwnProperty.call | ||
| cache[exp] = parsedExpression; | ||
| if (cacheKey !== 'hasOwnProperty') { | ||
| // Only cache the value if it's not going to mess up the cache object | ||
| // This is more performant that using Object.prototype.hasOwnProperty.call | ||
| cache[cacheKey] = parsedExpression; | ||
| } | ||
| } | ||
|
|
||
| return oneTime || parsedExpression.constant ? oneTimeWrapper(parsedExpression) : parsedExpression; | ||
| return addInterceptor(parsedExpression, interceptorFn); | ||
|
|
||
| case 'function': | ||
| return exp; | ||
| return addInterceptor(exp, interceptorFn); | ||
|
|
||
| default: | ||
| return noop; | ||
| return addInterceptor(noop, interceptorFn); | ||
| } | ||
| }; | ||
|
|
||
| function oneTimeWrapper(expression) { | ||
| var stable = false, | ||
| lastValue; | ||
| oneTimeParseFn.literal = expression.literal; | ||
| oneTimeParseFn.constant = expression.constant; | ||
| oneTimeParseFn.assign = expression.assign; | ||
| return oneTimeParseFn; | ||
|
|
||
| function oneTimeParseFn(self, locals) { | ||
| if (!stable) { | ||
| lastValue = expression.constant && lastValue ? lastValue : expression(self, locals); | ||
| oneTimeParseFn.$$unwatch = isDefined(lastValue); | ||
| if (oneTimeParseFn.$$unwatch && self && self.$$postDigestQueue) { | ||
| self.$$postDigestQueue.push(function () { | ||
| // create a copy if the value is defined and it is not a $sce value | ||
| if ((stable = isDefined(lastValue)) && | ||
| (lastValue === null || !lastValue.$$unwrapTrustedValue)) { | ||
| lastValue = copy(lastValue, null); | ||
| } | ||
| }); | ||
| function oneTimeWatch(scope, listener, objectEquality, deregisterNotifier, parsedExpression) { | ||
| var unwatch, lastValue; | ||
| return unwatch = scope.$watch(function oneTimeWatch(scope) { | ||
| return parsedExpression(scope); | ||
| }, function oneTimeListener(value, old, scope) { | ||
| lastValue = value; | ||
| if (isFunction(listener)) { | ||
| listener.apply(this, arguments); | ||
| } | ||
| if (isDefined(value)) { | ||
| scope.$$postDigest(function () { | ||
| if (isDefined(lastValue)) { | ||
| unwatch(); | ||
| } | ||
| } | ||
| return lastValue; | ||
| }); | ||
| } | ||
| }, objectEquality, deregisterNotifier); | ||
| } | ||
|
|
||
| function constantWatch(scope, listener, objectEquality, deregisterNotifier, parsedExpression) { | ||
| var unwatch; | ||
| return unwatch = scope.$watch(function constantWatch(scope) { | ||
| return parsedExpression(scope); | ||
| }, function constantListener(value, old, scope) { | ||
| if (isFunction(listener)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the |
||
| listener.apply(this, arguments); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are you binding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's change this to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also above in oneTimeWatch |
||
| } | ||
| unwatch(); | ||
| }, objectEquality, deregisterNotifier); | ||
| } | ||
|
|
||
| function addInterceptor(parsedExpression, interceptorFn) { | ||
| if (isFunction(interceptorFn)) { | ||
| var fn = function interceptedExpression(scope, locals) { | ||
| var value = parsedExpression(scope, locals); | ||
| var result = interceptorFn(value, scope, locals); | ||
| // we only return the interceptor's result if the | ||
| // initial value is defined (for bind-once) | ||
| return isDefined(value) ? result : value; | ||
| }; | ||
| fn.$$watchDelegate = parsedExpression.$$watchDelegate; | ||
| return fn; | ||
| } else { | ||
| return parsedExpression; | ||
| } | ||
| }; | ||
| } | ||
| }]; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???