Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(607)

Side by Side Diff: tests/compiler/dart2js/equivalence/check_functions.dart

Issue 2963193003: Add equivalence testing on JS nodes to support different label names (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// Equivalence test functions for data objects. 5 /// Equivalence test functions for data objects.
6 6
7 library dart2js.equivalence.functions; 7 library dart2js.equivalence.functions;
8 8
9 import 'package:expect/expect.dart'; 9 import 'package:expect/expect.dart';
10 import 'package:compiler/src/common/resolution.dart'; 10 import 'package:compiler/src/common/resolution.dart';
11 import 'package:compiler/src/common_elements.dart'; 11 import 'package:compiler/src/common_elements.dart';
12 import 'package:compiler/src/compiler.dart'; 12 import 'package:compiler/src/compiler.dart';
13 import 'package:compiler/src/elements/types.dart'; 13 import 'package:compiler/src/elements/types.dart';
14 import 'package:compiler/src/elements/elements.dart'; 14 import 'package:compiler/src/elements/elements.dart';
15 import 'package:compiler/src/elements/entities.dart'; 15 import 'package:compiler/src/elements/entities.dart';
16 import 'package:compiler/src/enqueue.dart'; 16 import 'package:compiler/src/enqueue.dart';
17 import 'package:compiler/src/js/js_debug.dart' as js;
18 import 'package:compiler/src/js_backend/backend.dart';
17 import 'package:compiler/src/js_backend/backend_usage.dart'; 19 import 'package:compiler/src/js_backend/backend_usage.dart';
18 import 'package:compiler/src/js_backend/enqueuer.dart'; 20 import 'package:compiler/src/js_backend/enqueuer.dart';
19 import 'package:compiler/src/js_backend/native_data.dart'; 21 import 'package:compiler/src/js_backend/native_data.dart';
20 import 'package:compiler/src/js_backend/interceptor_data.dart'; 22 import 'package:compiler/src/js_backend/interceptor_data.dart';
21 import 'package:compiler/src/js_emitter/code_emitter_task.dart'; 23 import 'package:compiler/src/js_emitter/code_emitter_task.dart';
22 import 'package:compiler/src/js_emitter/model.dart'; 24 import 'package:compiler/src/js_emitter/model.dart';
23 import 'package:compiler/src/serialization/equivalence.dart'; 25 import 'package:compiler/src/serialization/equivalence.dart';
24 import 'package:compiler/src/universe/class_set.dart'; 26 import 'package:compiler/src/universe/class_set.dart';
25 import 'package:compiler/src/universe/world_builder.dart'; 27 import 'package:compiler/src/universe/world_builder.dart';
28 import 'package:compiler/src/util/util.dart';
26 import 'package:compiler/src/world.dart'; 29 import 'package:compiler/src/world.dart';
30 import 'package:js_ast/js_ast.dart' as js;
27 import 'check_helpers.dart'; 31 import 'check_helpers.dart';
28 32
29 void checkClosedWorlds(ClosedWorld closedWorld1, ClosedWorld closedWorld2, 33 void checkClosedWorlds(ClosedWorld closedWorld1, ClosedWorld closedWorld2,
30 {TestStrategy strategy: const TestStrategy(), 34 {TestStrategy strategy: const TestStrategy(),
31 bool allowExtra: false, 35 bool allowExtra: false,
32 bool verbose: false, 36 bool verbose: false,
33 bool allowMissingClosureClasses: false}) { 37 bool allowMissingClosureClasses: false}) {
34 if (verbose) { 38 if (verbose) {
35 print(closedWorld1.dump()); 39 print(closedWorld1.dump());
36 print(closedWorld2.dump()); 40 print(closedWorld2.dump());
(...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 (a, b) => a.name.key == b.name.key); 858 (a, b) => a.name.key == b.name.key);
855 } 859 }
856 860
857 // TODO(johnniwinther): Check all class properties. 861 // TODO(johnniwinther): Check all class properties.
858 void checkEmitterClasses(Class class1, Class class2) { 862 void checkEmitterClasses(Class class1, Class class2) {
859 checkLists(class1.methods, class2.methods, 'methods', 863 checkLists(class1.methods, class2.methods, 'methods',
860 (a, b) => a.name.key == b.name.key); 864 (a, b) => a.name.key == b.name.key);
861 checkLists(class1.isChecks, class2.isChecks, 'isChecks', 865 checkLists(class1.isChecks, class2.isChecks, 'isChecks',
862 (a, b) => a.name.key == b.name.key); 866 (a, b) => a.name.key == b.name.key);
863 } 867 }
868
869 void checkGeneratedCode(JavaScriptBackend backend1, JavaScriptBackend backend2,
870 {bool elementEquivalence(Entity a, Entity b): _areEntitiesEquivalent}) {
871 checkMaps(backend1.generatedCode, backend2.generatedCode, 'generatedCode',
872 elementEquivalence, areJsNodesEquivalent,
873 valueToString: js.nodeToString);
874 }
875
876 bool areJsNodesEquivalent(js.Node node1, js.Node node2) {
877 return new JsEquivalenceVisitor().testNodes(node1, node2);
878 }
879
880 class JsEquivalenceVisitor implements js.NodeVisitor<bool> {
881 Link<js.Node> stack1 = const Link<js.Node>();
882 Link<js.Node> stack2 = const Link<js.Node>();
883 Map<String, String> labelsMap = <String, String>{};
884
885 void push(js.Node node1, js.Node node2) {
886 stack1 = stack1.prepend(node1);
887 stack2 = stack2.prepend(node2);
888 }
889
890 js.Node peek() => stack2.head;
891
892 void pop() {
893 stack1 = stack1.tail;
894 stack2 = stack2.tail;
895 }
896
897 bool failAt(js.Node node1, js.Node node2) {
898 print('Node mismatch:');
899 print(' ${js.nodeToString(node1)}');
900 print(' ${js.nodeToString(node2)}');
901 return false;
902 }
903
904 bool testValues(Object object1, Object object2) {
905 if (object1 != object2) {
906 print('Value mismatch:');
907 print(' ${object1}');
908 print(' ${object2}');
909 print('at');
910 print(' ${js.nodeToString(stack1.head)}');
911 print(' ${js.nodeToString(stack2.head)}');
912 }
913 return object1 == object2;
914 }
915
916 bool testLabels(String object1, String object2) {
917 if (object1 == null && object2 == null) return true;
918 if (labelsMap.containsKey(object1)) {
919 String expectedValue = labelsMap[object1];
920 if (expectedValue != object2) {
921 print('Value mismatch:');
922 print(' ${object1}');
923 print(' found ${object2}, expected ${expectedValue}');
924 print('at');
925 print(' ${js.nodeToString(stack1.head)}');
926 print(' ${js.nodeToString(stack2.head)}');
927 }
928 return expectedValue == object2;
929 } else {
930 labelsMap[object1] = object2;
931 return true;
932 }
933 }
934
935 bool testNodes(js.Node node1, js.Node node2) {
936 if (identical(node1, node2)) return true;
937 if (node1 == null || node2 == null) return failAt(node1, node2);
938 push(node1, node2);
939 bool result = node1.accept(this);
940 pop();
941 return result;
942 }
943
944 bool testNodeLists(List<js.Node> list1, List<js.Node> list2) {
945 int index = 0;
946 while (index < list1.length && index < list2.length) {
947 if (!testNodes(list1[index], list2[index])) return false;
948 index++;
949 }
950 if (index < list1.length) {
951 return failAt(list1[index], null);
952 } else if (index < list2.length) {
953 return failAt(list2[index], null);
954 }
955 return true;
956 }
957
958 @override
959 bool visitProgram(js.Program node) {
960 if (peek() is! js.Program) return failAt(node, peek());
961 js.Program other = peek();
962 return testNodeLists(node.body, other.body);
963 }
964
965 @override
966 bool visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
967 if (peek() is! js.InterpolatedDeclaration) return failAt(node, peek());
968 js.InterpolatedDeclaration other = peek();
969 return testValues(node.nameOrPosition, other.nameOrPosition);
970 }
971
972 @override
973 bool visitInterpolatedStatement(js.InterpolatedStatement node) {
974 if (peek() is! js.InterpolatedStatement) return failAt(node, peek());
975 js.InterpolatedStatement other = peek();
976 return testValues(node.nameOrPosition, other.nameOrPosition);
977 }
978
979 @override
980 bool visitInterpolatedSelector(js.InterpolatedSelector node) {
981 if (peek() is! js.InterpolatedSelector) return failAt(node, peek());
982 js.InterpolatedSelector other = peek();
983 return testValues(node.nameOrPosition, other.nameOrPosition);
984 }
985
986 @override
987 bool visitInterpolatedParameter(js.InterpolatedParameter node) {
988 if (peek() is! js.InterpolatedParameter) return failAt(node, peek());
989 js.InterpolatedParameter other = peek();
990 return testValues(node.nameOrPosition, other.nameOrPosition);
991 }
992
993 @override
994 bool visitInterpolatedLiteral(js.InterpolatedLiteral node) {
995 if (peek() is! js.InterpolatedLiteral) return failAt(node, peek());
996 js.InterpolatedLiteral other = peek();
997 return testValues(node.nameOrPosition, other.nameOrPosition);
998 }
999
1000 @override
1001 bool visitInterpolatedExpression(js.InterpolatedExpression node) {
1002 if (peek() is! js.InterpolatedExpression) return failAt(node, peek());
1003 js.InterpolatedExpression other = peek();
1004 return testValues(node.nameOrPosition, other.nameOrPosition);
1005 }
1006
1007 @override
1008 bool visitComment(js.Comment node) {
1009 if (peek() is! js.Comment) return failAt(node, peek());
1010 js.Comment other = peek();
1011 return testValues(node.comment, other.comment);
1012 }
1013
1014 @override
1015 bool visitAwait(js.Await node) {
1016 if (peek() is! js.Await) return failAt(node, peek());
1017 js.Await other = peek();
1018 return testNodes(node.expression, other.expression);
1019 }
1020
1021 @override
1022 bool visitRegExpLiteral(js.RegExpLiteral node) {
1023 if (peek() is! js.RegExpLiteral) return failAt(node, peek());
1024 js.RegExpLiteral other = peek();
1025 return testValues(node.pattern, other.pattern);
1026 }
1027
1028 @override
1029 bool visitProperty(js.Property node) {
1030 if (peek() is! js.Property) return failAt(node, peek());
1031 js.Property other = peek();
1032 return testNodes(node.name, other.name) &&
1033 testNodes(node.value, other.value);
1034 }
1035
1036 @override
1037 bool visitObjectInitializer(js.ObjectInitializer node) {
1038 if (peek() is! js.ObjectInitializer) return failAt(node, peek());
1039 js.ObjectInitializer other = peek();
1040 return testNodeLists(node.properties, other.properties);
1041 }
1042
1043 @override
1044 bool visitArrayHole(js.ArrayHole node) {
1045 if (peek() is! js.ArrayHole) return failAt(node, peek());
1046 return true;
1047 }
1048
1049 @override
1050 bool visitArrayInitializer(js.ArrayInitializer node) {
1051 if (peek() is! js.ArrayInitializer) return failAt(node, peek());
1052 js.ArrayInitializer other = peek();
1053 return testNodeLists(node.elements, other.elements);
1054 }
1055
1056 @override
1057 bool visitName(js.Name node) {
1058 if (peek() is! js.Name) return failAt(node, peek());
1059 js.Name other = peek();
1060 return testValues(node.key, other.key);
1061 }
1062
1063 @override
1064 bool visitStringConcatenation(js.StringConcatenation node) {
1065 if (peek() is! js.StringConcatenation) return failAt(node, peek());
1066 js.StringConcatenation other = peek();
1067 return testNodeLists(node.parts, other.parts);
1068 }
1069
1070 @override
1071 bool visitLiteralNull(js.LiteralNull node) {
1072 if (peek() is! js.LiteralNull) return failAt(node, peek());
1073 return true;
1074 }
1075
1076 @override
1077 bool visitLiteralNumber(js.LiteralNumber node) {
1078 if (peek() is! js.LiteralNumber) return failAt(node, peek());
1079 js.LiteralNumber other = peek();
1080 return testValues(node.value, other.value);
1081 }
1082
1083 @override
1084 bool visitLiteralString(js.LiteralString node) {
1085 if (peek() is! js.LiteralString) return failAt(node, peek());
1086 js.LiteralString other = peek();
1087 return testValues(node.value, other.value);
1088 }
1089
1090 @override
1091 bool visitLiteralBool(js.LiteralBool node) {
1092 if (peek() is! js.LiteralBool) return failAt(node, peek());
1093 js.LiteralBool other = peek();
1094 return testValues(node.value, other.value);
1095 }
1096
1097 @override
1098 bool visitDeferredString(js.DeferredString node) {
1099 if (peek() is! js.DeferredString) return failAt(node, peek());
1100 js.DeferredString other = peek();
1101 return testValues(node.value, other.value);
1102 }
1103
1104 @override
1105 bool visitDeferredNumber(js.DeferredNumber node) {
1106 if (peek() is! js.DeferredNumber) return failAt(node, peek());
1107 js.DeferredNumber other = peek();
1108 return testValues(node.value, other.value);
1109 }
1110
1111 @override
1112 bool visitDeferredExpression(js.DeferredExpression node) {
1113 if (peek() is! js.DeferredExpression) return failAt(node, peek());
1114 js.DeferredExpression other = peek();
1115 return testNodes(node.value, other.value);
1116 }
1117
1118 @override
1119 bool visitFun(js.Fun node) {
1120 if (peek() is! js.Fun) return failAt(node, peek());
1121 js.Fun other = peek();
1122 return testNodeLists(node.params, other.params) &&
1123 testNodes(node.body, other.body) &&
1124 testValues(node.asyncModifier, other.asyncModifier);
1125 }
1126
1127 @override
1128 bool visitNamedFunction(js.NamedFunction node) {
1129 if (peek() is! js.NamedFunction) return failAt(node, peek());
1130 js.NamedFunction other = peek();
1131 return testNodes(node.name, other.name) &&
1132 testNodes(node.function, other.function);
1133 }
1134
1135 @override
1136 bool visitAccess(js.PropertyAccess node) {
1137 if (peek() is! js.PropertyAccess) return failAt(node, peek());
1138 js.PropertyAccess other = peek();
1139 return testNodes(node.receiver, other.receiver) &&
1140 testNodes(node.selector, other.selector);
1141 }
1142
1143 @override
1144 bool visitParameter(js.Parameter node) {
1145 if (peek() is! js.Parameter) return failAt(node, peek());
1146 js.Parameter other = peek();
1147 return testValues(node.name, other.name);
1148 }
1149
1150 @override
1151 bool visitVariableDeclaration(js.VariableDeclaration node) {
1152 if (peek() is! js.VariableDeclaration) return failAt(node, peek());
1153 js.VariableDeclaration other = peek();
1154 return testValues(node.name, other.name) &&
1155 testValues(node.allowRename, other.allowRename);
1156 }
1157
1158 @override
1159 bool visitThis(js.This node) {
1160 if (peek() is! js.This) return failAt(node, peek());
1161 return true;
1162 }
1163
1164 @override
1165 bool visitVariableUse(js.VariableUse node) {
1166 if (peek() is! js.VariableUse) return failAt(node, peek());
1167 js.VariableUse other = peek();
1168 return testValues(node.name, other.name);
1169 }
1170
1171 @override
1172 bool visitPostfix(js.Postfix node) {
1173 if (peek() is! js.Postfix) return failAt(node, peek());
1174 js.Postfix other = peek();
1175 return testValues(node.op, other.op) &&
1176 testNodes(node.argument, other.argument);
1177 }
1178
1179 @override
1180 bool visitPrefix(js.Prefix node) {
1181 if (peek() is! js.Prefix) return failAt(node, peek());
1182 js.Prefix other = peek();
1183 return testValues(node.op, other.op) &&
1184 testNodes(node.argument, other.argument);
1185 }
1186
1187 @override
1188 bool visitBinary(js.Binary node) {
1189 if (peek() is! js.Binary) return failAt(node, peek());
1190 js.Binary other = peek();
1191 return testNodes(node.left, other.left) &&
1192 testValues(node.op, other.op) &&
1193 testNodes(node.right, other.right);
1194 }
1195
1196 @override
1197 bool visitCall(js.Call node) {
1198 if (peek() is! js.Call) return failAt(node, peek());
1199 js.Call other = peek();
1200 return testNodes(node.target, other.target) &&
1201 testNodeLists(node.arguments, other.arguments);
1202 }
1203
1204 @override
1205 bool visitNew(js.New node) {
1206 if (peek() is! js.New) return failAt(node, peek());
1207 js.New other = peek();
1208 return testNodes(node.target, other.target) &&
1209 testNodeLists(node.arguments, other.arguments);
1210 }
1211
1212 @override
1213 bool visitConditional(js.Conditional node) {
1214 if (peek() is! js.Conditional) return failAt(node, peek());
1215 js.Conditional other = peek();
1216 return testNodes(node.condition, other.condition) &&
1217 testNodes(node.then, other.then) &&
1218 testNodes(node.otherwise, other.otherwise);
1219 }
1220
1221 @override
1222 bool visitVariableInitialization(js.VariableInitialization node) {
1223 if (peek() is! js.VariableInitialization) return failAt(node, peek());
1224 js.VariableInitialization other = peek();
1225 return testNodes(node.declaration, other.declaration) &&
1226 testNodes(node.leftHandSide, other.leftHandSide) &&
1227 testValues(node.op, other.op) &&
1228 testNodes(node.value, other.value);
1229 }
1230
1231 @override
1232 bool visitAssignment(js.Assignment node) {
1233 if (peek() is! js.Assignment) return failAt(node, peek());
1234 js.Assignment other = peek();
1235 return testNodes(node.leftHandSide, other.leftHandSide) &&
1236 testValues(node.op, other.op) &&
1237 testNodes(node.value, other.value);
1238 }
1239
1240 @override
1241 bool visitVariableDeclarationList(js.VariableDeclarationList node) {
1242 if (peek() is! js.VariableDeclarationList) return failAt(node, peek());
1243 js.VariableDeclarationList other = peek();
1244 return testNodeLists(node.declarations, other.declarations);
1245 }
1246
1247 @override
1248 bool visitLiteralExpression(js.LiteralExpression node) {
1249 if (peek() is! js.LiteralExpression) return failAt(node, peek());
1250 js.LiteralExpression other = peek();
1251 return testValues(node.template, other.template) &&
1252 testNodeLists(node.inputs, other.inputs);
1253 }
1254
1255 @override
1256 bool visitDartYield(js.DartYield node) {
1257 if (peek() is! js.DartYield) return failAt(node, peek());
1258 js.DartYield other = peek();
1259 return testNodes(node.expression, other.expression) &&
1260 testValues(node.hasStar, other.hasStar);
1261 }
1262
1263 @override
1264 bool visitLiteralStatement(js.LiteralStatement node) {
1265 if (peek() is! js.LiteralStatement) return failAt(node, peek());
1266 js.LiteralStatement other = peek();
1267 return testValues(node.code, other.code);
1268 }
1269
1270 @override
1271 bool visitLabeledStatement(js.LabeledStatement node) {
1272 if (peek() is! js.LabeledStatement) return failAt(node, peek());
1273 js.LabeledStatement other = peek();
1274 return testLabels(node.label, other.label) &&
1275 testNodes(node.body, other.body);
1276 }
1277
1278 @override
1279 bool visitFunctionDeclaration(js.FunctionDeclaration node) {
1280 if (peek() is! js.FunctionDeclaration) return failAt(node, peek());
1281 js.FunctionDeclaration other = peek();
1282 return testNodes(node.name, other.name) &&
1283 testNodes(node.function, other.function);
1284 }
1285
1286 @override
1287 bool visitDefault(js.Default node) {
1288 if (peek() is! js.Default) return failAt(node, peek());
1289 js.Default other = peek();
1290 return testNodes(node.body, other.body);
1291 }
1292
1293 @override
1294 bool visitCase(js.Case node) {
1295 if (peek() is! js.Case) return failAt(node, peek());
1296 js.Case other = peek();
1297 return testNodes(node.expression, other.expression) &&
1298 testNodes(node.body, other.body);
1299 }
1300
1301 @override
1302 bool visitSwitch(js.Switch node) {
1303 if (peek() is! js.Switch) return failAt(node, peek());
1304 js.Switch other = peek();
1305 return testNodes(node.key, other.key) &&
1306 testNodeLists(node.cases, other.cases);
1307 }
1308
1309 @override
1310 bool visitCatch(js.Catch node) {
1311 if (peek() is! js.Catch) return failAt(node, peek());
1312 js.Catch other = peek();
1313 return testNodes(node.declaration, other.declaration) &&
1314 testNodes(node.body, other.body);
1315 }
1316
1317 @override
1318 bool visitTry(js.Try node) {
1319 if (peek() is! js.Try) return failAt(node, peek());
1320 js.Try other = peek();
1321 return testNodes(node.body, other.body) &&
1322 testNodes(node.catchPart, other.catchPart) &&
1323 testNodes(node.finallyPart, other.finallyPart);
1324 }
1325
1326 @override
1327 bool visitThrow(js.Throw node) {
1328 if (peek() is! js.Throw) return failAt(node, peek());
1329 js.Throw other = peek();
1330 return testNodes(node.expression, other.expression);
1331 }
1332
1333 @override
1334 bool visitReturn(js.Return node) {
1335 if (peek() is! js.Return) return failAt(node, peek());
1336 js.Return other = peek();
1337 return testNodes(node.value, other.value);
1338 }
1339
1340 @override
1341 bool visitBreak(js.Break node) {
1342 if (peek() is! js.Break) return failAt(node, peek());
1343 js.Break other = peek();
1344 return testLabels(node.targetLabel, other.targetLabel);
1345 }
1346
1347 @override
1348 bool visitContinue(js.Continue node) {
1349 if (peek() is! js.Continue) return failAt(node, peek());
1350 js.Continue other = peek();
1351 return testLabels(node.targetLabel, other.targetLabel);
1352 }
1353
1354 @override
1355 bool visitDo(js.Do node) {
1356 if (peek() is! js.Do) return failAt(node, peek());
1357 js.Do other = peek();
1358 return testNodes(node.condition, other.condition) &&
1359 testNodes(node.body, other.body);
1360 }
1361
1362 @override
1363 bool visitWhile(js.While node) {
1364 if (peek() is! js.While) return failAt(node, peek());
1365 js.While other = peek();
1366 return testNodes(node.condition, other.condition) &&
1367 testNodes(node.body, other.body);
1368 }
1369
1370 @override
1371 bool visitForIn(js.ForIn node) {
1372 if (peek() is! js.ForIn) return failAt(node, peek());
1373 js.ForIn other = peek();
1374 return testNodes(node.leftHandSide, other.leftHandSide) &&
1375 testNodes(node.object, other.object) &&
1376 testNodes(node.body, other.body);
1377 }
1378
1379 @override
1380 bool visitFor(js.For node) {
1381 if (peek() is! js.For) return failAt(node, peek());
1382 js.For other = peek();
1383 return testNodes(node.init, other.init) &&
1384 testNodes(node.condition, other.condition) &&
1385 testNodes(node.update, other.update) &&
1386 testNodes(node.body, other.body);
1387 }
1388
1389 @override
1390 bool visitIf(js.If node) {
1391 if (peek() is! js.If) return failAt(node, peek());
1392 js.If other = peek();
1393 return testNodes(node.condition, other.condition) &&
1394 testNodes(node.then, other.then) &&
1395 testNodes(node.otherwise, other.otherwise);
1396 }
1397
1398 @override
1399 bool visitEmptyStatement(js.EmptyStatement node) {
1400 if (peek() is! js.EmptyStatement) return failAt(node, peek());
1401 return true;
1402 }
1403
1404 @override
1405 bool visitExpressionStatement(js.ExpressionStatement node) {
1406 if (peek() is! js.ExpressionStatement) return failAt(node, peek());
1407 js.ExpressionStatement other = peek();
1408 return testNodes(node.expression, other.expression);
1409 }
1410
1411 @override
1412 bool visitBlock(js.Block node) {
1413 if (peek() is! js.Block) return failAt(node, peek());
1414 js.Block other = peek();
1415 return testNodeLists(node.statements, other.statements);
1416 }
1417 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698