Skip to content

Commit 708c4e3

Browse files
committed
0718603 chore(perf): return perf metrics from AngularProfiler
1 parent 62e446a commit 708c4e3

9 files changed

Lines changed: 25 additions & 202 deletions

File tree

‎BUILD_INFO‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
Fri Apr 15 21:51:13 UTC 2016
2-
9c712595ca398ae3aa3074428f0d0f168a62e96e
1+
Fri Apr 15 21:56:01 UTC 2016
2+
0718603e3e8a88aecda08bc1de48302ce0081ece

‎lib/src/compiler/expression_parser/lexer.dart‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ const $BACKSLASH = 92;
156156
const $RBRACKET = 93;
157157
const $CARET = 94;
158158
const $_ = 95;
159-
const $BT = 96;
160159
const $a = 97,
161160
$e = 101,
162161
$f = 102,
@@ -439,10 +438,6 @@ bool isExponentSign(num code) {
439438
return code == $MINUS || code == $PLUS;
440439
}
441440

442-
bool isQuote(num code) {
443-
return identical(code, $SQ) || identical(code, $DQ) || identical(code, $BT);
444-
}
445-
446441
num unescape(num code) {
447442
switch (code) {
448443
case $n:

‎lib/src/compiler/expression_parser/parser.dart‎

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import "lexer.dart"
1111
Lexer,
1212
EOF,
1313
isIdentifier,
14-
isQuote,
1514
Token,
1615
$PERIOD,
1716
$COLON,
@@ -22,8 +21,7 @@ import "lexer.dart"
2221
$LBRACE,
2322
$RBRACE,
2423
$LPAREN,
25-
$RPAREN,
26-
$SLASH;
24+
$RPAREN;
2725
import "ast.dart"
2826
show
2927
AST,
@@ -76,7 +74,7 @@ class Parser {
7674
Parser(this._lexer) {}
7775
ASTWithSource parseAction(String input, dynamic location) {
7876
this._checkNoInterpolation(input, location);
79-
var tokens = this._lexer.tokenize(this._stripComments(input));
77+
var tokens = this._lexer.tokenize(input);
8078
var ast = new _ParseAST(input, location, tokens, true).parseChain();
8179
return new ASTWithSource(ast, input, location);
8280
}
@@ -106,7 +104,7 @@ class Parser {
106104
return quote;
107105
}
108106
this._checkNoInterpolation(input, location);
109-
var tokens = this._lexer.tokenize(this._stripComments(input));
107+
var tokens = this._lexer.tokenize(input);
110108
return new _ParseAST(input, location, tokens, false).parseChain();
111109
}
112110

@@ -131,8 +129,7 @@ class Parser {
131129
if (split == null) return null;
132130
var expressions = [];
133131
for (var i = 0; i < split.expressions.length; ++i) {
134-
var tokens =
135-
this._lexer.tokenize(this._stripComments(split.expressions[i]));
132+
var tokens = this._lexer.tokenize(split.expressions[i]);
136133
var ast = new _ParseAST(input, location, tokens, false).parseChain();
137134
expressions.add(ast);
138135
}
@@ -169,27 +166,6 @@ class Parser {
169166
return new ASTWithSource(new LiteralPrimitive(input), input, location);
170167
}
171168

172-
String _stripComments(String input) {
173-
var i = this._commentStart(input);
174-
return isPresent(i) ? input.substring(0, i).trim() : input;
175-
}
176-
177-
num _commentStart(String input) {
178-
var outerQuote = null;
179-
for (var i = 0; i < input.length - 1; i++) {
180-
var char = StringWrapper.charCodeAt(input, i);
181-
var nextChar = StringWrapper.charCodeAt(input, i + 1);
182-
if (identical(char, $SLASH) && nextChar == $SLASH && isBlank(outerQuote))
183-
return i;
184-
if (identical(outerQuote, char)) {
185-
outerQuote = null;
186-
} else if (isBlank(outerQuote) && isQuote(char)) {
187-
outerQuote = char;
188-
}
189-
}
190-
return null;
191-
}
192-
193169
void _checkNoInterpolation(String input, dynamic location) {
194170
var parts = StringWrapper.split(input, INTERPOLATION_REGEXP);
195171
if (parts.length > 1) {

‎lib/src/i18n/i18n_html_parser.dart‎

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,14 @@ import "shared.dart"
3030
partition,
3131
Part,
3232
stringifyNodes,
33-
meaning,
34-
getPhNameFromBinding,
35-
dedupePhName;
33+
meaning;
3634

3735
const _I18N_ATTR = "i18n";
3836
const _PLACEHOLDER_ELEMENT = "ph";
3937
const _NAME_ATTR = "name";
4038
const _I18N_ATTR_PREFIX = "i18n-";
4139
var _PLACEHOLDER_EXPANDED_REGEXP =
42-
RegExpWrapper.create('''\\<ph(\\s)+name=("(\\w)+")\\>\\<\\/ph\\>''');
40+
RegExpWrapper.create('''\\<ph(\\s)+name=("(\\d)+")\\>\\<\\/ph\\>''');
4341

4442
/**
4543
* Creates an i18n-ed version of the parsed template.
@@ -325,32 +323,22 @@ class I18nHtmlParser implements HtmlParser {
325323

326324
String _replacePlaceholdersWithExpressions(
327325
String message, List<String> exps, ParseSourceSpan sourceSpan) {
328-
var expMap = this._buildExprMap(exps);
329326
return RegExpWrapper.replaceAll(_PLACEHOLDER_EXPANDED_REGEXP, message,
330327
(match) {
331328
var nameWithQuotes = match[2];
332329
var name = nameWithQuotes.substring(1, nameWithQuotes.length - 1);
333-
return this._convertIntoExpression(name, expMap, sourceSpan);
330+
var index = NumberWrapper.parseInt(name, 10);
331+
return this._convertIntoExpression(index, exps, sourceSpan);
334332
});
335333
}
336334

337-
Map<String, String> _buildExprMap(List<String> exps) {
338-
var expMap = new Map<String, String>();
339-
var usedNames = new Map<String, num>();
340-
for (var i = 0; i < exps.length; i++) {
341-
var phName = getPhNameFromBinding(exps[i], i);
342-
expMap[dedupePhName(usedNames, phName)] = exps[i];
343-
}
344-
return expMap;
345-
}
346-
347335
_convertIntoExpression(
348-
String name, Map<String, String> expMap, ParseSourceSpan sourceSpan) {
349-
if (expMap.containsKey(name)) {
350-
return '''{{${ expMap [ name ]}}}''';
336+
num index, List<String> exps, ParseSourceSpan sourceSpan) {
337+
if (index >= 0 && index < exps.length) {
338+
return '''{{${ exps [ index ]}}}''';
351339
} else {
352340
throw new I18nError(
353-
sourceSpan, '''Invalid interpolation name \'${ name}\'''');
341+
sourceSpan, '''Invalid interpolation index \'${ index}\'''');
354342
}
355343
}
356344
}

‎lib/src/i18n/shared.dart‎

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,13 @@ import "package:angular2/src/compiler/html_ast.dart"
1111
HtmlTextAst,
1212
HtmlCommentAst,
1313
htmlVisitAll;
14-
import "package:angular2/src/facade/lang.dart"
15-
show isPresent, isBlank, StringWrapper;
14+
import "package:angular2/src/facade/lang.dart" show isPresent, isBlank;
1615
import "message.dart" show Message;
1716
import "package:angular2/src/compiler/expression_parser/parser.dart"
1817
show Parser;
1918

2019
const I18N_ATTR = "i18n";
2120
const I18N_ATTR_PREFIX = "i18n-";
22-
var CUSTOM_PH_EXP = new RegExp(
23-
r'\/\/[\s\S]*i18n[\s\S]*\([\s\S]*ph[\s\S]*=[\s\S]*"([\s\S]*?)"[\s\S]*\)');
2421

2522
/**
2623
* An i18n error.
@@ -127,15 +124,12 @@ String removeInterpolation(
127124
String value, ParseSourceSpan source, Parser parser) {
128125
try {
129126
var parsed = parser.splitInterpolation(value, source.toString());
130-
var usedNames = new Map<String, num>();
131127
if (isPresent(parsed)) {
132128
var res = "";
133129
for (var i = 0; i < parsed.strings.length; ++i) {
134130
res += parsed.strings[i];
135131
if (i != parsed.strings.length - 1) {
136-
var customPhName = getPhNameFromBinding(parsed.expressions[i], i);
137-
customPhName = dedupePhName(usedNames, customPhName);
138-
res += '''<ph name="${ customPhName}"/>''';
132+
res += '''<ph name="${ i}"/>''';
139133
}
140134
}
141135
return res;
@@ -147,22 +141,6 @@ String removeInterpolation(
147141
}
148142
}
149143

150-
String getPhNameFromBinding(String input, num index) {
151-
var customPhMatch = StringWrapper.split(input, CUSTOM_PH_EXP);
152-
return customPhMatch.length > 1 ? customPhMatch[1] : '''${ index}''';
153-
}
154-
155-
String dedupePhName(Map<String, num> usedNames, String name) {
156-
var duplicateNameCount = usedNames[name];
157-
if (isPresent(duplicateNameCount)) {
158-
usedNames[name] = duplicateNameCount + 1;
159-
return '''${ name}_${ duplicateNameCount}''';
160-
} else {
161-
usedNames[name] = 1;
162-
return name;
163-
}
164-
}
165-
166144
String stringifyNodes(List<HtmlAst> nodes, Parser parser) {
167145
var visitor = new _StringifyVisitor(parser);
168146
return htmlVisitAll(visitor, nodes).join("");

‎lib/src/platform/browser/tools/common_tools.dart‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ import "package:angular2/src/facade/lang.dart" show isPresent, NumberWrapper;
77
import "package:angular2/src/facade/browser.dart" show window;
88
import "package:angular2/src/platform/dom/dom_adapter.dart" show DOM;
99

10+
class ChangeDetectionPerfRecord {
11+
num msPerTick;
12+
num numTicks;
13+
ChangeDetectionPerfRecord(this.msPerTick, this.numTicks) {}
14+
}
15+
1016
/**
1117
* Entry point for all Angular debug tools. This object corresponds to the `ng`
1218
* global variable accessible in the dev console.
@@ -43,7 +49,7 @@ class AngularProfiler {
4349
* ng.profiler.timeChangeDetection({record: true})
4450
* ```
4551
*/
46-
timeChangeDetection(dynamic config) {
52+
ChangeDetectionPerfRecord timeChangeDetection(dynamic config) {
4753
var record = isPresent(config) && config["record"];
4854
var profileName = "Change Detection";
4955
// Profiler is not available in Android browsers, nor in IE 9 without dev tools opened
@@ -72,5 +78,6 @@ class AngularProfiler {
7278
window.console.log('''ran ${ numTicks} change detection cycles''');
7379
window.console
7480
.log('''${ NumberWrapper . toFixed ( msPerTick , 2 )} ms per check''');
81+
return new ChangeDetectionPerfRecord(msPerTick, numTicks);
7582
}
7683
}

‎test/compiler/expression_parser/parser_spec.dart‎

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,6 @@ main() {
101101
it("should parse grouped expressions", () {
102102
checkAction("(1 + 2) * 3", "1 + 2 * 3");
103103
});
104-
it("should ignore comments in expressions", () {
105-
checkAction("a //comment", "a");
106-
});
107-
it("should retain // in string literals", () {
108-
checkAction(
109-
'''"http://www.google.com"''', '''"http://www.google.com"''');
110-
});
111104
it("should parse an empty string", () {
112105
checkAction("");
113106
});
@@ -271,16 +264,6 @@ main() {
271264
it("should parse conditional expression", () {
272265
checkBinding("a < b ? a : b");
273266
});
274-
it("should ignore comments in bindings", () {
275-
checkBinding("a //comment", "a");
276-
});
277-
it("should retain // in string literals", () {
278-
checkBinding(
279-
'''"http://www.google.com"''', '''"http://www.google.com"''');
280-
});
281-
it("should retain // in : microsyntax", () {
282-
checkBinding("one:a//b", "one:a//b");
283-
});
284267
});
285268
describe("parseTemplateBindings", () {
286269
keys(List<dynamic> templateBindings) {
@@ -424,29 +407,6 @@ main() {
424407
\'bar\' + \'baz\' }}''',
425408
'''{{ "foo" + "bar" + "baz" }}''');
426409
});
427-
describe("comments", () {
428-
it("should ignore comments in interpolation expressions", () {
429-
checkInterpolation("{{a //comment}}", "{{ a }}");
430-
});
431-
it("should retain // in single quote strings", () {
432-
checkInterpolation('''{{ \'http://www.google.com\' }}''',
433-
'''{{ "http://www.google.com" }}''');
434-
});
435-
it("should retain // in double quote strings", () {
436-
checkInterpolation('''{{ "http://www.google.com" }}''',
437-
'''{{ "http://www.google.com" }}''');
438-
});
439-
it("should ignore comments after string literals", () {
440-
checkInterpolation('''{{ "a//b" //comment }}''', '''{{ "a//b" }}''');
441-
});
442-
it("should retain // in complex strings", () {
443-
checkInterpolation('''{{"//a\'//b`//c`//d\'//e" //comment}}''',
444-
'''{{ "//a\'//b`//c`//d\'//e" }}''');
445-
});
446-
it("should retain // in nested, unterminated strings", () {
447-
checkInterpolation('''{{ "a\'b`" //comment}}''', '''{{ "a\'b`" }}''');
448-
});
449-
});
450410
});
451411
describe("parseSimpleBinding", () {
452412
it("should parse a field access", () {

‎test/i18n/i18n_html_parser_spec.dart‎

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -88,38 +88,6 @@ main() {
8888
[HtmlAttrAst, "value", "{{b}} or {{a}}"]
8989
]);
9090
});
91-
it("should handle interpolation with custom placeholder names", () {
92-
Map<String, String> translations = {};
93-
translations[id(new Message(
94-
"<ph name=\"FIRST\"/> and <ph name=\"SECOND\"/>", null, null))] =
95-
"<ph name=\"SECOND\"/> or <ph name=\"FIRST\"/>";
96-
expect(humanizeDom(parse(
97-
'''<div value=\'{{a //i18n(ph="FIRST")}} and {{b //i18n(ph="SECOND")}}\' i18n-value></div>''',
98-
translations))).toEqual([
99-
[HtmlElementAst, "div", 0],
100-
[
101-
HtmlAttrAst,
102-
"value",
103-
"{{b //i18n(ph=\"SECOND\")}} or {{a //i18n(ph=\"FIRST\")}}"
104-
]
105-
]);
106-
});
107-
it("should handle interpolation with duplicate placeholder names", () {
108-
Map<String, String> translations = {};
109-
translations[id(new Message(
110-
"<ph name=\"FIRST\"/> and <ph name=\"FIRST_1\"/>", null, null))] =
111-
"<ph name=\"FIRST_1\"/> or <ph name=\"FIRST\"/>";
112-
expect(humanizeDom(parse(
113-
'''<div value=\'{{a //i18n(ph="FIRST")}} and {{b //i18n(ph="FIRST")}}\' i18n-value></div>''',
114-
translations))).toEqual([
115-
[HtmlElementAst, "div", 0],
116-
[
117-
HtmlAttrAst,
118-
"value",
119-
"{{b //i18n(ph=\"FIRST\")}} or {{a //i18n(ph=\"FIRST\")}}"
120-
]
121-
]);
122-
});
12391
it("should handle nested html", () {
12492
Map<String, String> translations = {};
12593
translations[id(new Message(
@@ -241,7 +209,7 @@ main() {
241209
"hi <ph name=\"99\"/>";
242210
expect(humanizeErrors(
243211
parse("<div value='hi {{a}}' i18n-value></div>", translations)
244-
.errors)).toEqual(["Invalid interpolation name '99'"]);
212+
.errors)).toEqual(["Invalid interpolation index '99'"]);
245213
});
246214
});
247215
});

0 commit comments

Comments
 (0)