| Index: tests/compiler/dart2js/equivalence/check_functions.dart
|
| diff --git a/tests/compiler/dart2js/equivalence/check_functions.dart b/tests/compiler/dart2js/equivalence/check_functions.dart
|
| index 7ce86d35c1ad2a5eb3701d9b9f0b3759b7484ce9..4d1f8b4bd93929ef61b010689f604feb3255ab99 100644
|
| --- a/tests/compiler/dart2js/equivalence/check_functions.dart
|
| +++ b/tests/compiler/dart2js/equivalence/check_functions.dart
|
| @@ -14,6 +14,8 @@ import 'package:compiler/src/elements/types.dart';
|
| import 'package:compiler/src/elements/elements.dart';
|
| import 'package:compiler/src/elements/entities.dart';
|
| import 'package:compiler/src/enqueue.dart';
|
| +import 'package:compiler/src/js/js_debug.dart' as js;
|
| +import 'package:compiler/src/js_backend/backend.dart';
|
| import 'package:compiler/src/js_backend/backend_usage.dart';
|
| import 'package:compiler/src/js_backend/enqueuer.dart';
|
| import 'package:compiler/src/js_backend/native_data.dart';
|
| @@ -23,7 +25,9 @@ import 'package:compiler/src/js_emitter/model.dart';
|
| import 'package:compiler/src/serialization/equivalence.dart';
|
| import 'package:compiler/src/universe/class_set.dart';
|
| import 'package:compiler/src/universe/world_builder.dart';
|
| +import 'package:compiler/src/util/util.dart';
|
| import 'package:compiler/src/world.dart';
|
| +import 'package:js_ast/js_ast.dart' as js;
|
| import 'check_helpers.dart';
|
|
|
| void checkClosedWorlds(ClosedWorld closedWorld1, ClosedWorld closedWorld2,
|
| @@ -861,3 +865,553 @@ void checkEmitterClasses(Class class1, Class class2) {
|
| checkLists(class1.isChecks, class2.isChecks, 'isChecks',
|
| (a, b) => a.name.key == b.name.key);
|
| }
|
| +
|
| +void checkGeneratedCode(JavaScriptBackend backend1, JavaScriptBackend backend2,
|
| + {bool elementEquivalence(Entity a, Entity b): _areEntitiesEquivalent}) {
|
| + checkMaps(backend1.generatedCode, backend2.generatedCode, 'generatedCode',
|
| + elementEquivalence, areJsNodesEquivalent,
|
| + valueToString: js.nodeToString);
|
| +}
|
| +
|
| +bool areJsNodesEquivalent(js.Node node1, js.Node node2) {
|
| + return new JsEquivalenceVisitor().testNodes(node1, node2);
|
| +}
|
| +
|
| +class JsEquivalenceVisitor implements js.NodeVisitor<bool> {
|
| + Link<js.Node> stack1 = const Link<js.Node>();
|
| + Link<js.Node> stack2 = const Link<js.Node>();
|
| + Map<String, String> labelsMap = <String, String>{};
|
| +
|
| + void push(js.Node node1, js.Node node2) {
|
| + stack1 = stack1.prepend(node1);
|
| + stack2 = stack2.prepend(node2);
|
| + }
|
| +
|
| + js.Node peek() => stack2.head;
|
| +
|
| + void pop() {
|
| + stack1 = stack1.tail;
|
| + stack2 = stack2.tail;
|
| + }
|
| +
|
| + bool failAt(js.Node node1, js.Node node2) {
|
| + print('Node mismatch:');
|
| + print(' ${js.nodeToString(node1)}');
|
| + print(' ${js.nodeToString(node2)}');
|
| + return false;
|
| + }
|
| +
|
| + bool testValues(Object object1, Object object2) {
|
| + if (object1 != object2) {
|
| + print('Value mismatch:');
|
| + print(' ${object1}');
|
| + print(' ${object2}');
|
| + print('at');
|
| + print(' ${js.nodeToString(stack1.head)}');
|
| + print(' ${js.nodeToString(stack2.head)}');
|
| + }
|
| + return object1 == object2;
|
| + }
|
| +
|
| + bool testLabels(String object1, String object2) {
|
| + if (object1 == null && object2 == null) return true;
|
| + if (labelsMap.containsKey(object1)) {
|
| + String expectedValue = labelsMap[object1];
|
| + if (expectedValue != object2) {
|
| + print('Value mismatch:');
|
| + print(' ${object1}');
|
| + print(' found ${object2}, expected ${expectedValue}');
|
| + print('at');
|
| + print(' ${js.nodeToString(stack1.head)}');
|
| + print(' ${js.nodeToString(stack2.head)}');
|
| + }
|
| + return expectedValue == object2;
|
| + } else {
|
| + labelsMap[object1] = object2;
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + bool testNodes(js.Node node1, js.Node node2) {
|
| + if (identical(node1, node2)) return true;
|
| + if (node1 == null || node2 == null) return failAt(node1, node2);
|
| + push(node1, node2);
|
| + bool result = node1.accept(this);
|
| + pop();
|
| + return result;
|
| + }
|
| +
|
| + bool testNodeLists(List<js.Node> list1, List<js.Node> list2) {
|
| + int index = 0;
|
| + while (index < list1.length && index < list2.length) {
|
| + if (!testNodes(list1[index], list2[index])) return false;
|
| + index++;
|
| + }
|
| + if (index < list1.length) {
|
| + return failAt(list1[index], null);
|
| + } else if (index < list2.length) {
|
| + return failAt(list2[index], null);
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + @override
|
| + bool visitProgram(js.Program node) {
|
| + if (peek() is! js.Program) return failAt(node, peek());
|
| + js.Program other = peek();
|
| + return testNodeLists(node.body, other.body);
|
| + }
|
| +
|
| + @override
|
| + bool visitInterpolatedDeclaration(js.InterpolatedDeclaration node) {
|
| + if (peek() is! js.InterpolatedDeclaration) return failAt(node, peek());
|
| + js.InterpolatedDeclaration other = peek();
|
| + return testValues(node.nameOrPosition, other.nameOrPosition);
|
| + }
|
| +
|
| + @override
|
| + bool visitInterpolatedStatement(js.InterpolatedStatement node) {
|
| + if (peek() is! js.InterpolatedStatement) return failAt(node, peek());
|
| + js.InterpolatedStatement other = peek();
|
| + return testValues(node.nameOrPosition, other.nameOrPosition);
|
| + }
|
| +
|
| + @override
|
| + bool visitInterpolatedSelector(js.InterpolatedSelector node) {
|
| + if (peek() is! js.InterpolatedSelector) return failAt(node, peek());
|
| + js.InterpolatedSelector other = peek();
|
| + return testValues(node.nameOrPosition, other.nameOrPosition);
|
| + }
|
| +
|
| + @override
|
| + bool visitInterpolatedParameter(js.InterpolatedParameter node) {
|
| + if (peek() is! js.InterpolatedParameter) return failAt(node, peek());
|
| + js.InterpolatedParameter other = peek();
|
| + return testValues(node.nameOrPosition, other.nameOrPosition);
|
| + }
|
| +
|
| + @override
|
| + bool visitInterpolatedLiteral(js.InterpolatedLiteral node) {
|
| + if (peek() is! js.InterpolatedLiteral) return failAt(node, peek());
|
| + js.InterpolatedLiteral other = peek();
|
| + return testValues(node.nameOrPosition, other.nameOrPosition);
|
| + }
|
| +
|
| + @override
|
| + bool visitInterpolatedExpression(js.InterpolatedExpression node) {
|
| + if (peek() is! js.InterpolatedExpression) return failAt(node, peek());
|
| + js.InterpolatedExpression other = peek();
|
| + return testValues(node.nameOrPosition, other.nameOrPosition);
|
| + }
|
| +
|
| + @override
|
| + bool visitComment(js.Comment node) {
|
| + if (peek() is! js.Comment) return failAt(node, peek());
|
| + js.Comment other = peek();
|
| + return testValues(node.comment, other.comment);
|
| + }
|
| +
|
| + @override
|
| + bool visitAwait(js.Await node) {
|
| + if (peek() is! js.Await) return failAt(node, peek());
|
| + js.Await other = peek();
|
| + return testNodes(node.expression, other.expression);
|
| + }
|
| +
|
| + @override
|
| + bool visitRegExpLiteral(js.RegExpLiteral node) {
|
| + if (peek() is! js.RegExpLiteral) return failAt(node, peek());
|
| + js.RegExpLiteral other = peek();
|
| + return testValues(node.pattern, other.pattern);
|
| + }
|
| +
|
| + @override
|
| + bool visitProperty(js.Property node) {
|
| + if (peek() is! js.Property) return failAt(node, peek());
|
| + js.Property other = peek();
|
| + return testNodes(node.name, other.name) &&
|
| + testNodes(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitObjectInitializer(js.ObjectInitializer node) {
|
| + if (peek() is! js.ObjectInitializer) return failAt(node, peek());
|
| + js.ObjectInitializer other = peek();
|
| + return testNodeLists(node.properties, other.properties);
|
| + }
|
| +
|
| + @override
|
| + bool visitArrayHole(js.ArrayHole node) {
|
| + if (peek() is! js.ArrayHole) return failAt(node, peek());
|
| + return true;
|
| + }
|
| +
|
| + @override
|
| + bool visitArrayInitializer(js.ArrayInitializer node) {
|
| + if (peek() is! js.ArrayInitializer) return failAt(node, peek());
|
| + js.ArrayInitializer other = peek();
|
| + return testNodeLists(node.elements, other.elements);
|
| + }
|
| +
|
| + @override
|
| + bool visitName(js.Name node) {
|
| + if (peek() is! js.Name) return failAt(node, peek());
|
| + js.Name other = peek();
|
| + return testValues(node.key, other.key);
|
| + }
|
| +
|
| + @override
|
| + bool visitStringConcatenation(js.StringConcatenation node) {
|
| + if (peek() is! js.StringConcatenation) return failAt(node, peek());
|
| + js.StringConcatenation other = peek();
|
| + return testNodeLists(node.parts, other.parts);
|
| + }
|
| +
|
| + @override
|
| + bool visitLiteralNull(js.LiteralNull node) {
|
| + if (peek() is! js.LiteralNull) return failAt(node, peek());
|
| + return true;
|
| + }
|
| +
|
| + @override
|
| + bool visitLiteralNumber(js.LiteralNumber node) {
|
| + if (peek() is! js.LiteralNumber) return failAt(node, peek());
|
| + js.LiteralNumber other = peek();
|
| + return testValues(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitLiteralString(js.LiteralString node) {
|
| + if (peek() is! js.LiteralString) return failAt(node, peek());
|
| + js.LiteralString other = peek();
|
| + return testValues(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitLiteralBool(js.LiteralBool node) {
|
| + if (peek() is! js.LiteralBool) return failAt(node, peek());
|
| + js.LiteralBool other = peek();
|
| + return testValues(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitDeferredString(js.DeferredString node) {
|
| + if (peek() is! js.DeferredString) return failAt(node, peek());
|
| + js.DeferredString other = peek();
|
| + return testValues(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitDeferredNumber(js.DeferredNumber node) {
|
| + if (peek() is! js.DeferredNumber) return failAt(node, peek());
|
| + js.DeferredNumber other = peek();
|
| + return testValues(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitDeferredExpression(js.DeferredExpression node) {
|
| + if (peek() is! js.DeferredExpression) return failAt(node, peek());
|
| + js.DeferredExpression other = peek();
|
| + return testNodes(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitFun(js.Fun node) {
|
| + if (peek() is! js.Fun) return failAt(node, peek());
|
| + js.Fun other = peek();
|
| + return testNodeLists(node.params, other.params) &&
|
| + testNodes(node.body, other.body) &&
|
| + testValues(node.asyncModifier, other.asyncModifier);
|
| + }
|
| +
|
| + @override
|
| + bool visitNamedFunction(js.NamedFunction node) {
|
| + if (peek() is! js.NamedFunction) return failAt(node, peek());
|
| + js.NamedFunction other = peek();
|
| + return testNodes(node.name, other.name) &&
|
| + testNodes(node.function, other.function);
|
| + }
|
| +
|
| + @override
|
| + bool visitAccess(js.PropertyAccess node) {
|
| + if (peek() is! js.PropertyAccess) return failAt(node, peek());
|
| + js.PropertyAccess other = peek();
|
| + return testNodes(node.receiver, other.receiver) &&
|
| + testNodes(node.selector, other.selector);
|
| + }
|
| +
|
| + @override
|
| + bool visitParameter(js.Parameter node) {
|
| + if (peek() is! js.Parameter) return failAt(node, peek());
|
| + js.Parameter other = peek();
|
| + return testValues(node.name, other.name);
|
| + }
|
| +
|
| + @override
|
| + bool visitVariableDeclaration(js.VariableDeclaration node) {
|
| + if (peek() is! js.VariableDeclaration) return failAt(node, peek());
|
| + js.VariableDeclaration other = peek();
|
| + return testValues(node.name, other.name) &&
|
| + testValues(node.allowRename, other.allowRename);
|
| + }
|
| +
|
| + @override
|
| + bool visitThis(js.This node) {
|
| + if (peek() is! js.This) return failAt(node, peek());
|
| + return true;
|
| + }
|
| +
|
| + @override
|
| + bool visitVariableUse(js.VariableUse node) {
|
| + if (peek() is! js.VariableUse) return failAt(node, peek());
|
| + js.VariableUse other = peek();
|
| + return testValues(node.name, other.name);
|
| + }
|
| +
|
| + @override
|
| + bool visitPostfix(js.Postfix node) {
|
| + if (peek() is! js.Postfix) return failAt(node, peek());
|
| + js.Postfix other = peek();
|
| + return testValues(node.op, other.op) &&
|
| + testNodes(node.argument, other.argument);
|
| + }
|
| +
|
| + @override
|
| + bool visitPrefix(js.Prefix node) {
|
| + if (peek() is! js.Prefix) return failAt(node, peek());
|
| + js.Prefix other = peek();
|
| + return testValues(node.op, other.op) &&
|
| + testNodes(node.argument, other.argument);
|
| + }
|
| +
|
| + @override
|
| + bool visitBinary(js.Binary node) {
|
| + if (peek() is! js.Binary) return failAt(node, peek());
|
| + js.Binary other = peek();
|
| + return testNodes(node.left, other.left) &&
|
| + testValues(node.op, other.op) &&
|
| + testNodes(node.right, other.right);
|
| + }
|
| +
|
| + @override
|
| + bool visitCall(js.Call node) {
|
| + if (peek() is! js.Call) return failAt(node, peek());
|
| + js.Call other = peek();
|
| + return testNodes(node.target, other.target) &&
|
| + testNodeLists(node.arguments, other.arguments);
|
| + }
|
| +
|
| + @override
|
| + bool visitNew(js.New node) {
|
| + if (peek() is! js.New) return failAt(node, peek());
|
| + js.New other = peek();
|
| + return testNodes(node.target, other.target) &&
|
| + testNodeLists(node.arguments, other.arguments);
|
| + }
|
| +
|
| + @override
|
| + bool visitConditional(js.Conditional node) {
|
| + if (peek() is! js.Conditional) return failAt(node, peek());
|
| + js.Conditional other = peek();
|
| + return testNodes(node.condition, other.condition) &&
|
| + testNodes(node.then, other.then) &&
|
| + testNodes(node.otherwise, other.otherwise);
|
| + }
|
| +
|
| + @override
|
| + bool visitVariableInitialization(js.VariableInitialization node) {
|
| + if (peek() is! js.VariableInitialization) return failAt(node, peek());
|
| + js.VariableInitialization other = peek();
|
| + return testNodes(node.declaration, other.declaration) &&
|
| + testNodes(node.leftHandSide, other.leftHandSide) &&
|
| + testValues(node.op, other.op) &&
|
| + testNodes(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitAssignment(js.Assignment node) {
|
| + if (peek() is! js.Assignment) return failAt(node, peek());
|
| + js.Assignment other = peek();
|
| + return testNodes(node.leftHandSide, other.leftHandSide) &&
|
| + testValues(node.op, other.op) &&
|
| + testNodes(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitVariableDeclarationList(js.VariableDeclarationList node) {
|
| + if (peek() is! js.VariableDeclarationList) return failAt(node, peek());
|
| + js.VariableDeclarationList other = peek();
|
| + return testNodeLists(node.declarations, other.declarations);
|
| + }
|
| +
|
| + @override
|
| + bool visitLiteralExpression(js.LiteralExpression node) {
|
| + if (peek() is! js.LiteralExpression) return failAt(node, peek());
|
| + js.LiteralExpression other = peek();
|
| + return testValues(node.template, other.template) &&
|
| + testNodeLists(node.inputs, other.inputs);
|
| + }
|
| +
|
| + @override
|
| + bool visitDartYield(js.DartYield node) {
|
| + if (peek() is! js.DartYield) return failAt(node, peek());
|
| + js.DartYield other = peek();
|
| + return testNodes(node.expression, other.expression) &&
|
| + testValues(node.hasStar, other.hasStar);
|
| + }
|
| +
|
| + @override
|
| + bool visitLiteralStatement(js.LiteralStatement node) {
|
| + if (peek() is! js.LiteralStatement) return failAt(node, peek());
|
| + js.LiteralStatement other = peek();
|
| + return testValues(node.code, other.code);
|
| + }
|
| +
|
| + @override
|
| + bool visitLabeledStatement(js.LabeledStatement node) {
|
| + if (peek() is! js.LabeledStatement) return failAt(node, peek());
|
| + js.LabeledStatement other = peek();
|
| + return testLabels(node.label, other.label) &&
|
| + testNodes(node.body, other.body);
|
| + }
|
| +
|
| + @override
|
| + bool visitFunctionDeclaration(js.FunctionDeclaration node) {
|
| + if (peek() is! js.FunctionDeclaration) return failAt(node, peek());
|
| + js.FunctionDeclaration other = peek();
|
| + return testNodes(node.name, other.name) &&
|
| + testNodes(node.function, other.function);
|
| + }
|
| +
|
| + @override
|
| + bool visitDefault(js.Default node) {
|
| + if (peek() is! js.Default) return failAt(node, peek());
|
| + js.Default other = peek();
|
| + return testNodes(node.body, other.body);
|
| + }
|
| +
|
| + @override
|
| + bool visitCase(js.Case node) {
|
| + if (peek() is! js.Case) return failAt(node, peek());
|
| + js.Case other = peek();
|
| + return testNodes(node.expression, other.expression) &&
|
| + testNodes(node.body, other.body);
|
| + }
|
| +
|
| + @override
|
| + bool visitSwitch(js.Switch node) {
|
| + if (peek() is! js.Switch) return failAt(node, peek());
|
| + js.Switch other = peek();
|
| + return testNodes(node.key, other.key) &&
|
| + testNodeLists(node.cases, other.cases);
|
| + }
|
| +
|
| + @override
|
| + bool visitCatch(js.Catch node) {
|
| + if (peek() is! js.Catch) return failAt(node, peek());
|
| + js.Catch other = peek();
|
| + return testNodes(node.declaration, other.declaration) &&
|
| + testNodes(node.body, other.body);
|
| + }
|
| +
|
| + @override
|
| + bool visitTry(js.Try node) {
|
| + if (peek() is! js.Try) return failAt(node, peek());
|
| + js.Try other = peek();
|
| + return testNodes(node.body, other.body) &&
|
| + testNodes(node.catchPart, other.catchPart) &&
|
| + testNodes(node.finallyPart, other.finallyPart);
|
| + }
|
| +
|
| + @override
|
| + bool visitThrow(js.Throw node) {
|
| + if (peek() is! js.Throw) return failAt(node, peek());
|
| + js.Throw other = peek();
|
| + return testNodes(node.expression, other.expression);
|
| + }
|
| +
|
| + @override
|
| + bool visitReturn(js.Return node) {
|
| + if (peek() is! js.Return) return failAt(node, peek());
|
| + js.Return other = peek();
|
| + return testNodes(node.value, other.value);
|
| + }
|
| +
|
| + @override
|
| + bool visitBreak(js.Break node) {
|
| + if (peek() is! js.Break) return failAt(node, peek());
|
| + js.Break other = peek();
|
| + return testLabels(node.targetLabel, other.targetLabel);
|
| + }
|
| +
|
| + @override
|
| + bool visitContinue(js.Continue node) {
|
| + if (peek() is! js.Continue) return failAt(node, peek());
|
| + js.Continue other = peek();
|
| + return testLabels(node.targetLabel, other.targetLabel);
|
| + }
|
| +
|
| + @override
|
| + bool visitDo(js.Do node) {
|
| + if (peek() is! js.Do) return failAt(node, peek());
|
| + js.Do other = peek();
|
| + return testNodes(node.condition, other.condition) &&
|
| + testNodes(node.body, other.body);
|
| + }
|
| +
|
| + @override
|
| + bool visitWhile(js.While node) {
|
| + if (peek() is! js.While) return failAt(node, peek());
|
| + js.While other = peek();
|
| + return testNodes(node.condition, other.condition) &&
|
| + testNodes(node.body, other.body);
|
| + }
|
| +
|
| + @override
|
| + bool visitForIn(js.ForIn node) {
|
| + if (peek() is! js.ForIn) return failAt(node, peek());
|
| + js.ForIn other = peek();
|
| + return testNodes(node.leftHandSide, other.leftHandSide) &&
|
| + testNodes(node.object, other.object) &&
|
| + testNodes(node.body, other.body);
|
| + }
|
| +
|
| + @override
|
| + bool visitFor(js.For node) {
|
| + if (peek() is! js.For) return failAt(node, peek());
|
| + js.For other = peek();
|
| + return testNodes(node.init, other.init) &&
|
| + testNodes(node.condition, other.condition) &&
|
| + testNodes(node.update, other.update) &&
|
| + testNodes(node.body, other.body);
|
| + }
|
| +
|
| + @override
|
| + bool visitIf(js.If node) {
|
| + if (peek() is! js.If) return failAt(node, peek());
|
| + js.If other = peek();
|
| + return testNodes(node.condition, other.condition) &&
|
| + testNodes(node.then, other.then) &&
|
| + testNodes(node.otherwise, other.otherwise);
|
| + }
|
| +
|
| + @override
|
| + bool visitEmptyStatement(js.EmptyStatement node) {
|
| + if (peek() is! js.EmptyStatement) return failAt(node, peek());
|
| + return true;
|
| + }
|
| +
|
| + @override
|
| + bool visitExpressionStatement(js.ExpressionStatement node) {
|
| + if (peek() is! js.ExpressionStatement) return failAt(node, peek());
|
| + js.ExpressionStatement other = peek();
|
| + return testNodes(node.expression, other.expression);
|
| + }
|
| +
|
| + @override
|
| + bool visitBlock(js.Block node) {
|
| + if (peek() is! js.Block) return failAt(node, peek());
|
| + js.Block other = peek();
|
| + return testNodeLists(node.statements, other.statements);
|
| + }
|
| +}
|
|
|