Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit cb54250

Browse files
committed
refactor($parse): remove second closure
Removed second closure for `inputs` and use `inputsWatchDelegate` to know when the computation is partial
1 parent c6a09eb commit cb54250

File tree

2 files changed

+31
-33
lines changed

2 files changed

+31
-33
lines changed

src/ng/parse.js

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -716,9 +716,9 @@ ASTCompiler.prototype = {
716716
nextId: 0,
717717
filters: {},
718718
expensiveChecks: expensiveChecks,
719-
closure: {vars: ['clean'], fns: {}},
720719
fn: {vars: [], body: [], own: {}},
721-
assign: {vars: [], body: [], own: {}}
720+
assign: {vars: [], body: [], own: {}},
721+
inputs: []
722722
};
723723
var lastExpression;
724724
var i;
@@ -728,22 +728,19 @@ ASTCompiler.prototype = {
728728
var toWatch = useInputs(ast.body) ? ast.body[ast.body.length - 1].expression.toWatch : [];
729729
forEach(toWatch, function(watch, key) {
730730
var fnKey = 'fn' + key;
731-
self.state.computing = 'closure';
732-
watch.fixedId = self.nextId();
733-
watch.skipClean = true;
734-
self.state.closure.fns[fnKey] = self.state[fnKey] = {vars: [], body: [], own: {}};
731+
self.state[fnKey] = {vars: [], body: [], own: {}};
735732
self.state.computing = fnKey;
736-
self.recurse(watch);
737-
self.assign('clean', true);
738-
self.return(watch.fixedId);
739-
watch.skipClean = false;
733+
var intoId = self.nextId();
734+
self.recurse(watch, intoId);
735+
self.return(intoId);
736+
self.state.inputs.push(fnKey);
737+
watch.watchId = key;
740738
});
741739
this.state.computing = 'fn';
742740
for (i = 0; i < ast.body.length; ++i) {
743741
if (lastExpression) this.current().body.push(lastExpression, ';');
744742
this.recurse(ast.body[i].expression, undefined, undefined, function(expr) { lastExpression = expr; });
745743
}
746-
this.assign('clean', false);
747744
if (lastExpression) this.return(lastExpression);
748745
var extra = '';
749746
if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) {
@@ -760,17 +757,14 @@ ASTCompiler.prototype = {
760757
// This is a woraround for this until we do a better job at only removing the prefix only when we should.
761758
'"' + this.USE + ' ' + this.STRICT + '";\n' +
762759
this.filterPrefix() +
763-
'return function(){' +
764-
this.varsPrefix('closure') +
765-
'var fn = function(s,l){' +
760+
'var fn = function(s,l,i){' +
766761
this.varsPrefix('fn') +
767762
this.body('fn') +
768763
'};' +
769764
extra +
770765
this.watchFns() +
771766
'fn.literal=literal;fn.constant=constant;' +
772-
'return fn;' +
773-
'};';
767+
'return fn;';
774768

775769
var isLiteral = ast.body.length === 1 && (
776770
ast.body[0].expression.type === AST.Literal ||
@@ -810,10 +804,9 @@ ASTCompiler.prototype = {
810804

811805
watchFns: function() {
812806
var result = [];
813-
var fns = [];
807+
var fns = this.state.inputs;
814808
var self = this;
815-
forEach(this.state.closure.fns, function(_, name) {
816-
fns.push(name);
809+
forEach(fns, function(name) {
817810
result.push(
818811
'var ' + name + ' = function(s,l){' +
819812
self.varsPrefix(name) +
@@ -877,24 +870,24 @@ ASTCompiler.prototype = {
877870
break;
878871
case AST.LogicalExpression:
879872
intoId = intoId || this.nextId();
880-
this.if(ast.fixedId && !ast.skipClean ? '!clean' : true, function() {
873+
this.if(isDefined(ast.watchId) ? '!i' : true, function() {
881874
self.recurse(ast.left, intoId);
882875
self.if(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId));
883876
recursionFn(intoId);
884877
self.assign(ast.fixedId, intoId);
885878
}, function() {
886-
self.assign(intoId, ast.fixedId);
879+
self.assign(intoId, self.computedMember('i', ast.watchId));
887880
});
888881
break;
889882
case AST.ConditionalExpression:
890883
intoId = intoId || this.nextId();
891-
this.if(ast.fixedId && !ast.skipClean ? '!clean' : true, function() {
884+
this.if(isDefined(ast.watchId) ? '!i' : true, function() {
892885
self.recurse(ast.test, intoId);
893886
self.if(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId));
894887
recursionFn(intoId);
895888
self.assign(ast.fixedId, intoId);
896889
}, function() {
897-
self.assign(intoId, ast.fixedId);
890+
self.assign(intoId, self.computedMember('i', ast.watchId));
898891
});
899892
break;
900893
case AST.Identifier:
@@ -904,7 +897,7 @@ ASTCompiler.prototype = {
904897
nameId.computed = false;
905898
nameId.name = ast.name;
906899
}
907-
this.if(ast.fixedId && !ast.skipClean ? '!clean' : true, function() {
900+
this.if(isDefined(ast.watchId) ? '!i' : true, function() {
908901
ensureSafeMemberName(ast.name);
909902
self.if(self.not(self.getHasOwnProperty('l', ast.name)),
910903
function() {
@@ -924,13 +917,13 @@ ASTCompiler.prototype = {
924917
recursionFn(intoId);
925918
self.assign(ast.fixedId, intoId);
926919
}, function() {
927-
self.assign(intoId, ast.fixedId);
920+
self.assign(intoId, self.computedMember('i', ast.watchId));
928921
});
929922
break;
930923
case AST.MemberExpression:
931924
left = nameId && (nameId.context = this.nextId()) || this.nextId();
932925
intoId = intoId || this.nextId();
933-
this.if(ast.fixedId && !ast.skipClean ? '!clean' : true, function() {
926+
this.if(isDefined(ast.watchId) ? '!i' : true, function() {
934927
self.recurse(ast.object, left, undefined, function() {
935928
self.if(self.notNull(left), function() {
936929
if (ast.computed) {
@@ -966,12 +959,12 @@ ASTCompiler.prototype = {
966959
}, !!create);
967960
self.assign(ast.fixedId, intoId);
968961
}, function() {
969-
self.assign(intoId, ast.fixedId);
962+
self.assign(intoId, self.computedMember('i', ast.watchId));
970963
});
971964
break;
972965
case AST.CallExpression:
973966
intoId = intoId || this.nextId();
974-
this.if(ast.fixedId && !ast.skipClean ? '!clean' : true, function() {
967+
this.if(isDefined(ast.watchId) ? '!i' : true, function() {
975968
if (ast.filter) {
976969
right = self.filter(ast.callee.name);
977970
args = [];
@@ -1011,7 +1004,7 @@ ASTCompiler.prototype = {
10111004
}
10121005
self.assign(ast.fixedId, intoId);
10131006
}, function() {
1014-
self.assign(intoId, ast.fixedId);
1007+
self.assign(intoId, self.computedMember('i', ast.watchId));
10151008
});
10161009
break;
10171010
case AST.AssignmentExpression:
@@ -1261,7 +1254,7 @@ ASTInterpreter.prototype = {
12611254
ast.body[0].expression.type === AST.ArrayExpression ||
12621255
ast.body[0].expression.type === AST.ObjectExpression);
12631256
fn.constant = ast.body.length === 1 && ast.body[0].expression.constant;
1264-
return valueFn(fn);
1257+
return fn;
12651258
},
12661259

12671260
recurse: function(ast, context, create) {
@@ -1691,7 +1684,7 @@ function $ParseProvider() {
16911684
expressionFactory = parser.parse(exp);
16921685
cache[cacheKey] = expressionFactory;
16931686
}
1694-
parsedExpression = expressionFactory();
1687+
parsedExpression = expressionFactory;
16951688
if (parsedExpression.constant) {
16961689
parsedExpression.$$watchDelegate = constantWatchDelegate;
16971690
} else if (oneTime) {
@@ -1745,7 +1738,7 @@ function $ParseProvider() {
17451738
return scope.$watch(function expressionInputWatch(scope) {
17461739
var newInputValue = inputExpressions(scope);
17471740
if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) {
1748-
lastResult = parsedExpression(scope);
1741+
lastResult = parsedExpression(scope, undefined, [newInputValue]);
17491742
oldInputValue = newInputValue && getValueOf(newInputValue);
17501743
}
17511744
return lastResult;
@@ -1768,7 +1761,7 @@ function $ParseProvider() {
17681761
}
17691762

17701763
if (changed) {
1771-
lastResult = parsedExpression(scope);
1764+
lastResult = parsedExpression(scope, undefined, oldInputValueOfValues);
17721765
}
17731766

17741767
return lastResult;

test/ng/parseSpec.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2710,6 +2710,11 @@ describe('parser', function() {
27102710
});
27112711

27122712
describe('one-time binding', function() {
2713+
it('should always use the cache', inject(function($parse) {
2714+
expect($parse('foo')).toBe($parse('foo'));
2715+
expect($parse('::foo')).toBe($parse('::foo'));
2716+
}));
2717+
27132718
it('should not affect calling the parseFn directly', inject(function($parse, $rootScope) {
27142719
var fn = $parse('::foo');
27152720
$rootScope.$watch(fn);

0 commit comments

Comments
 (0)