Skip to content

Commit 2617bb7

Browse files
mheveryvicb
authored andcommitted
fix(filters): make filters required and pass it to all evals
1 parent 4e53f73 commit 2617bb7

13 files changed

+67
-67
lines changed

lib/core/parser/dynamic_parser.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import 'package:angular/core/module.dart' show FilterMap, NgInjectableService;
55
import 'package:angular/core/parser/parser.dart';
66
import 'package:angular/core/parser/lexer.dart';
77
import 'package:angular/core/parser/dynamic_parser_impl.dart';
8-
import 'package:angular/core/parser/syntax.dart' show defaultFilterMap;
98

109
import 'package:angular/core/parser/eval.dart';
1110
import 'package:angular/core/parser/utils.dart' show EvalError;
@@ -46,7 +45,7 @@ class DynamicExpression extends Expression {
4645
accept(Visitor visitor) => _expression.accept(visitor);
4746
toString() => _expression.toString();
4847

49-
eval(scope, [FilterMap filters = defaultFilterMap]) {
48+
eval(scope, FilterMap filters) {
5049
try {
5150
return _expression.eval(scope, filters);
5251
} on EvalError catch (e, s) {

lib/core/parser/eval.dart

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export 'package:angular/core/parser/eval_calls.dart';
99

1010
class Chain extends syntax.Chain {
1111
Chain(List<syntax.Expression> expressions) : super(expressions);
12-
eval(scope, [FilterMap filters]) {
12+
eval(scope, FilterMap filters) {
1313
var result;
1414
for (int i = 0; i < expressions.length; i++) {
1515
var last = expressions[i].eval(scope, filters);
@@ -25,39 +25,45 @@ class Filter extends syntax.Filter {
2525
this.allArguments)
2626
: super(expression, name, arguments);
2727

28-
eval(scope, [FilterMap filters]) =>
29-
Function.apply(filters(name), evalList(scope, allArguments, filters));
28+
eval(scope, FilterMap filters) {
29+
if (filters == null) {
30+
throw 'No NgFilter: $name found!';
31+
}
32+
return Function.apply(filters(name), evalList(scope, allArguments, filters));
33+
}
3034
}
3135

3236
class Assign extends syntax.Assign {
3337
Assign(syntax.Expression target, value) : super(target, value);
34-
eval(scope, [FilterMap filters]) =>
38+
eval(scope, FilterMap filters) =>
3539
target.assign(scope, value.eval(scope, filters));
3640
}
3741

3842
class Conditional extends syntax.Conditional {
3943
Conditional(syntax.Expression condition,
4044
syntax.Expression yes, syntax.Expression no)
4145
: super(condition, yes, no);
42-
eval(scope, [FilterMap filters]) => toBool(condition.eval(scope, filters))
46+
eval(scope, FilterMap filters) => toBool(condition.eval(scope, filters))
4347
? yes.eval(scope, filters)
4448
: no.eval(scope, filters);
4549
}
4650

4751
class PrefixNot extends syntax.Prefix {
4852
PrefixNot(syntax.Expression expression) : super('!', expression);
49-
eval(scope, [FilterMap filters]) => !toBool(expression.eval(scope, filters));
53+
eval(scope, FilterMap filters) => !toBool(expression.eval(scope, filters));
5054
}
5155

5256
class Binary extends syntax.Binary {
5357
Binary(String operation, syntax.Expression left, syntax.Expression right):
5458
super(operation, left, right);
55-
eval(scope, [FilterMap filters]) {
59+
eval(scope, FilterMap filters) {
5660
var lValue = left.eval(scope, filters);
5761
switch (operation) {
58-
case '&&': return toBool(lValue) && toBool(this.right.eval(scope, filters));
59-
case '||': return toBool(lValue) || toBool(this.right.eval(scope, filters));
62+
// evaluates the rValue only if required
63+
case '&&': return toBool(lValue) && toBool(right.eval(scope, filters));
64+
case '||': return toBool(lValue) || toBool(right.eval(scope, filters));
6065
}
66+
6167
var rValue = right.eval(scope, filters);
6268

6369
// Null check for the operations.
@@ -97,22 +103,23 @@ class Binary extends syntax.Binary {
97103

98104
class LiteralPrimitive extends syntax.LiteralPrimitive {
99105
LiteralPrimitive(dynamic value) : super(value);
100-
eval(scope, [FilterMap filters]) => value;
106+
eval(scope, FilterMap filters) => value;
101107
}
102108

103109
class LiteralString extends syntax.LiteralString {
104110
LiteralString(String value) : super(value);
105-
eval(scope, [FilterMap filters]) => value;
111+
eval(scope, FilterMap filters) => value;
106112
}
107113

108114
class LiteralArray extends syntax.LiteralArray {
109115
LiteralArray(List<syntax.Expression> elements) : super(elements);
110-
eval(scope, [FilterMap filters]) =>
116+
eval(scope, FilterMap filters) =>
111117
elements.map((e) => e.eval(scope, filters)).toList();
112118
}
113119

114120
class LiteralObject extends syntax.LiteralObject {
115-
LiteralObject(List<String> keys, List<syntax.Expression>values) : super(keys, values);
116-
eval(scope, [FilterMap filters]) =>
121+
LiteralObject(List<String> keys, List<syntax.Expression>values)
122+
: super(keys, values);
123+
eval(scope, FilterMap filters) =>
117124
new Map.fromIterables(keys, values.map((e) => e.eval(scope, filters)));
118125
}

lib/core/parser/eval_access.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,24 @@ import 'package:angular/core/module.dart';
99
class AccessScope extends syntax.AccessScope with AccessReflective {
1010
final Symbol symbol;
1111
AccessScope(String name) : super(name), symbol = newSymbol(name);
12-
eval(scope, [FilterMap filters]) => _eval(scope);
12+
eval(scope, FilterMap filters) => _eval(scope);
1313
assign(scope, value) => _assign(scope, scope, value);
1414
}
1515

1616
class AccessScopeFast extends syntax.AccessScope with AccessFast {
1717
final Getter getter;
1818
final Setter setter;
1919
AccessScopeFast(String name, this.getter, this.setter) : super(name);
20-
eval(scope, [FilterMap filters]) => _eval(scope);
20+
eval(scope, FilterMap filters) => _eval(scope);
2121
assign(scope, value) => _assign(scope, scope, value);
2222
}
2323

2424
class AccessMember extends syntax.AccessMember with AccessReflective {
2525
final Symbol symbol;
2626
AccessMember(object, String name)
2727
: super(object, name), symbol = newSymbol(name);
28-
eval(scope, [FilterMap filters]) => _eval(object.eval(scope, filters));
29-
assign(scope, value) => _assign(scope, object.eval(scope), value);
28+
eval(scope, FilterMap filters) => _eval(object.eval(scope, filters));
29+
assign(scope, value) => _assign(scope, object.eval(scope, null), value);
3030
_assignToNonExisting(scope, value) => object.assign(scope, { name: value });
3131
}
3232

@@ -35,16 +35,16 @@ class AccessMemberFast extends syntax.AccessMember with AccessFast {
3535
final Setter setter;
3636
AccessMemberFast(object, String name, this.getter, this.setter)
3737
: super(object, name);
38-
eval(scope, [FilterMap filters]) => _eval(object.eval(scope, filters));
39-
assign(scope, value) => _assign(scope, object.eval(scope), value);
38+
eval(scope, FilterMap filters) => _eval(object.eval(scope, filters));
39+
assign(scope, value) => _assign(scope, object.eval(scope, null), value);
4040
_assignToNonExisting(scope, value) => object.assign(scope, { name: value });
4141
}
4242

4343
class AccessKeyed extends syntax.AccessKeyed {
4444
AccessKeyed(object, key) : super(object, key);
45-
eval(scope, [FilterMap filters]) =>
45+
eval(scope, FilterMap filters) =>
4646
getKeyed(object.eval(scope, filters), key.eval(scope, filters));
47-
assign(scope, value) => setKeyed(object.eval(scope), key.eval(scope), value);
47+
assign(scope, value) => setKeyed(object.eval(scope, null), key.eval(scope, null), value);
4848
}
4949

5050

lib/core/parser/eval_calls.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,48 +10,48 @@ class CallScope extends syntax.CallScope with CallReflective {
1010
CallScope(name, arguments)
1111
: super(name, arguments),
1212
symbol = newSymbol(name);
13-
eval(scope, [FilterMap filters]) => _eval(scope, scope);
13+
eval(scope, FilterMap filters) => _eval(scope, scope);
1414
}
1515

1616
class CallMember extends syntax.CallMember with CallReflective {
1717
final Symbol symbol;
1818
CallMember(object, name, arguments)
1919
: super(object, name, arguments),
2020
symbol = newSymbol(name);
21-
eval(scope, [FilterMap filters]) => _eval(scope, object.eval(scope, filters));
21+
eval(scope, FilterMap filters) => _eval(scope, object.eval(scope, filters));
2222
}
2323

2424
class CallScopeFast0 extends syntax.CallScope with CallFast {
2525
final Function function;
2626
CallScopeFast0(name, arguments, this.function) : super(name, arguments);
27-
eval(scope, [FilterMap filters]) => _evaluate0(scope);
27+
eval(scope, FilterMap filters) => _evaluate0(scope);
2828
}
2929

3030
class CallScopeFast1 extends syntax.CallScope with CallFast {
3131
final Function function;
3232
CallScopeFast1(name, arguments, this.function) : super(name, arguments);
33-
eval(scope, [FilterMap filters]) =>
33+
eval(scope, FilterMap filters) =>
3434
_evaluate1(scope, arguments[0].eval(scope, filters));
3535
}
3636

3737
class CallMemberFast0 extends syntax.CallMember with CallFast {
3838
final Function function;
3939
CallMemberFast0(object, name, arguments, this.function)
4040
: super(object, name, arguments);
41-
eval(scope, [FilterMap filters]) => _evaluate0(object.eval(scope, filters));
41+
eval(scope, FilterMap filters) => _evaluate0(object.eval(scope, filters));
4242
}
4343

4444
class CallMemberFast1 extends syntax.CallMember with CallFast {
4545
final Function function;
4646
CallMemberFast1(object, name, arguments, this.function)
4747
: super(object, name, arguments);
48-
eval(scope, [FilterMap filters]) => _evaluate1(object.eval(scope, filters),
48+
eval(scope, FilterMap filters) => _evaluate1(object.eval(scope, filters),
4949
arguments[0].eval(scope, filters));
5050
}
5151

5252
class CallFunction extends syntax.CallFunction {
5353
CallFunction(function, arguments) : super(function, arguments);
54-
eval(scope, [FilterMap filters]) {
54+
eval(scope, FilterMap filters) {
5555
var function = this.function.eval(scope, filters);
5656
if (function is! Function) {
5757
throw new EvalError('${this.function} is not a function');
@@ -80,7 +80,7 @@ abstract class CallReflective {
8080
List get arguments;
8181

8282
_eval(scope, holder) {
83-
List arguments = evalList(scope, this.arguments);
83+
List arguments = evalList(scope, this.arguments, null);
8484
if (!identical(holder, _cachedHolder)) {
8585
return _evaluteUncached(holder, arguments);
8686
}

lib/core/parser/static_parser.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class StaticExpression extends Expression {
4242
accept(Visitor visitor) => throw "Cannot visit static expression $this";
4343
toString() => _input;
4444

45-
eval(scope, [FilterMap filters = defaultFilterMap]) {
45+
eval(scope, FilterMap filters) {
4646
try {
4747
return _eval(scope, filters);
4848
} on EvalError catch (e, s) {
@@ -58,4 +58,4 @@ class StaticExpression extends Expression {
5858
throw e.unwrap("$this", s);
5959
}
6060
}
61-
}
61+
}

lib/core/parser/syntax.dart

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ abstract class Expression {
3939
bool get isAssignable => false;
4040
bool get isChain => false;
4141

42-
eval(scope, [FilterMap filters = defaultFilterMap]) =>
43-
throw new EvalError("Cannot evaluate $this");
44-
assign(scope, value) =>
45-
throw new EvalError("Cannot assign to $this");
46-
bind(context, [LocalsWrapper wrapper]) =>
47-
new BoundExpression(this, context, wrapper);
42+
eval(scope, FilterMap filters)
43+
=> throw new EvalError("Cannot evaluate $this");
44+
assign(scope, value)
45+
=> throw new EvalError("Cannot assign to $this");
46+
bind(context, [LocalsWrapper wrapper])
47+
=> new BoundExpression(this, context, wrapper);
4848

4949
accept(Visitor visitor);
5050
String toString() => Unparser.unparse(this);
@@ -56,7 +56,7 @@ class BoundExpression {
5656
final LocalsWrapper _wrapper;
5757
BoundExpression(this.expression, this._context, this._wrapper);
5858

59-
call([locals]) => expression.eval(_computeContext(locals));
59+
call([locals]) => expression.eval(_computeContext(locals), null);
6060
assign(value, [locals]) => expression.assign(_computeContext(locals), value);
6161

6262
_computeContext(locals) {
@@ -183,14 +183,3 @@ class LiteralObject extends Literal {
183183
LiteralObject(this.keys, this.values);
184184
accept(Visitor visitor) => visitor.visitLiteralObject(this);
185185
}
186-
187-
const defaultFilterMap = const _DefaultFilterMap();
188-
189-
class _DefaultFilterMap implements FilterMap {
190-
const _DefaultFilterMap();
191-
192-
call(name) => throw 'No NgFilter: $name found!';
193-
Type operator[](annotation) => null;
194-
forEach(fn) { }
195-
annotationsFor(type) => null;
196-
}

lib/core/parser/utils.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class EvalError {
2020
}
2121

2222
/// Evaluate the [list] in context of the [scope].
23-
List evalList(scope, List<Expression> list, [FilterMap filters]) {
23+
List evalList(scope, List<Expression> list, FilterMap filters) {
2424
int length = list.length;
2525
for (int cacheLength = _evalListCache.length; cacheLength <= length; cacheLength++) {
2626
_evalListCache.add(new List(cacheLength));

lib/core/scope.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ class Scope {
234234
expression is Function);
235235
if (expression is String && expression.isNotEmpty) {
236236
var obj = locals == null ? context : new ScopeLocals(context, locals);
237-
return rootScope._parser(expression).eval(obj);
237+
return rootScope._parser(expression).eval(obj, null);
238238
}
239239

240240
assert(locals == null);

lib/filter/filter.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class FilterFilter {
175175
bool _search(var item, var what) {
176176
if (what is Map) {
177177
return what.keys.every((key) => _search(
178-
(key == r'$') ? item : _parser(key).eval(item), what[key]));
178+
(key == r'$') ? item : _parser(key).eval(item, null), what[key]));
179179
} else if (item is Map) {
180180
return item.keys.any((k) => !k.startsWith(r'$') && _search(item[k], what));
181181
} else if (item is List) {

lib/filter/order_by.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ class OrderByFilter {
168168
mappers[i] = _nop;
169169
} else {
170170
Expression parsed = _parser(strExp);
171-
mappers[i] = (e) => parsed.eval(e);
171+
mappers[i] = (e) => parsed.eval(e, null);
172172
}
173173
} else if (expression is Mapper) {
174174
mappers[i] = (expression as Mapper);

perf/parser_perf.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ main() {
4949
Expression generatedExpr = generatedParser(expr);
5050
Expression hybridExpr = hybridParser(expr);
5151
var measure = (b) => statMeasure(b).mean_ops_sec;
52-
var gTime = measure(() => generatedExpr.eval(scope));
53-
var rTime = measure(() => reflectionExpr.eval(scope));
54-
var hTime = measure(() => hybridExpr.eval(scope));
52+
var gTime = measure(() => generatedExpr.eval(scope, null));
53+
var rTime = measure(() => reflectionExpr.eval(scope, null));
54+
var hTime = measure(() => hybridExpr.eval(scope, null));
5555
var iTime = measure(() => idealFn(scope));
5656
print('$expr => g: ${nf.format(gTime)} ops/sec ' +
5757
'r: ${nf.format(rTime)} ops/sec ' +

test/core/parser/parser_spec.dart

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,30 @@ class WithPrivateField {
4343

4444
toBool(x) => (x is num) ? x != 0 : x == true;
4545

46+
class RelaxedFilterExp {
47+
final exp;
48+
RelaxedFilterExp(this.exp);
49+
eval(o, [FilterMap f = null]) => exp.eval(o, f);
50+
assign(o, v) => exp.assign(o, v);
51+
bind(o, [l]) => exp.bind(o, l);
52+
}
53+
4654
main() {
4755
describe('parse', () {
4856
Map<String, dynamic> context;
49-
Parser<Expression> parser;
57+
Parser<Expression> _parser;
5058
FilterMap filters;
5159
beforeEachModule((Module module) {
5260
module.type(IncrementFilter);
5361
module.type(SubstringFilter);
5462
});
5563
beforeEach((Parser injectedParser, FilterMap injectedFilters) {
56-
parser = injectedParser;
64+
_parser = injectedParser;
5765
filters = injectedFilters;
5866
});
5967

68+
parser(String exp) => new RelaxedFilterExp(_parser(exp));
69+
6070
eval(String text, [FilterMap f])
6171
=> parser(text).eval(context, f == null ? filters : f);
6272
expectEval(String expr) => expect(() => eval(expr));
@@ -152,11 +162,6 @@ main() {
152162
});
153163

154164
describe('error handling', () {
155-
Parser<Expression> parser;
156-
157-
beforeEach((Parser p) {
158-
parser = p;
159-
});
160165

161166
// We only care about the error strings in the DynamicParser.
162167
var errStr = (x) {

test/core/parser/static_parser_spec.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ main() {
1919

2020

2121
it('should run a static function', (Parser parser) {
22-
expect(parser('1').eval(null)).toEqual(1);
22+
expect(parser('1').eval(null, null)).toEqual(1);
2323
});
2424

2525

0 commit comments

Comments
 (0)