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