| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 import 'dart:async'; |
| 5 import 'package:expect/expect.dart'; | 6 import 'package:expect/expect.dart'; |
| 7 import 'package:async_helper/async_helper.dart'; |
| 6 import 'mock_compiler.dart'; | 8 import 'mock_compiler.dart'; |
| 7 import '../../../sdk/lib/_internal/compiler/implementation/js/js.dart' as jsAst; | 9 import '../../../sdk/lib/_internal/compiler/implementation/js/js.dart' as jsAst; |
| 8 import '../../../sdk/lib/_internal/compiler/implementation/js/js.dart' show js; | 10 import '../../../sdk/lib/_internal/compiler/implementation/js/js.dart' show js; |
| 9 | 11 |
| 10 void testExpression(String expression, [String expect = ""]) { | 12 Future testExpression(String expression, [String expect = ""]) { |
| 11 jsAst.Node node = js(expression); | 13 jsAst.Node node = js(expression); |
| 12 MockCompiler compiler = new MockCompiler(); | 14 return MockCompiler.create((MockCompiler compiler) { |
| 13 String jsText = | 15 String jsText = |
| 14 jsAst.prettyPrint(node, | 16 jsAst.prettyPrint(node, |
| 15 compiler, | 17 compiler, |
| 16 allowVariableMinification: false).getText(); | 18 allowVariableMinification: false).getText(); |
| 17 if (expect == "") { | 19 if (expect == "") { |
| 18 Expect.stringEquals(expression, jsText); | 20 Expect.stringEquals(expression, jsText); |
| 19 } else { | 21 } else { |
| 20 Expect.stringEquals(expect, jsText); | 22 Expect.stringEquals(expect, jsText); |
| 21 } | 23 } |
| 24 }); |
| 22 } | 25 } |
| 23 | 26 |
| 24 void testError(String expression, [String expect = ""]) { | 27 Future testError(String expression, [String expect = ""]) { |
| 25 bool doCheck(exception) { | 28 return new Future.sync(() { |
| 26 Expect.isTrue(exception.toString().contains(expect)); | 29 bool doCheck(exception) { |
| 27 return true; | 30 Expect.isTrue(exception.toString().contains(expect)); |
| 28 } | 31 return true; |
| 29 Expect.throws(() => js(expression), doCheck); | 32 } |
| 33 Expect.throws(() => js(expression), doCheck); |
| 34 }); |
| 30 } | 35 } |
| 31 | |
| 32 | |
| 33 | 36 |
| 34 void main() { | 37 void main() { |
| 35 // Asterisk indicates deviations from real JS. | 38 asyncTest(() => Future.wait([ |
| 36 // Simple var test. | 39 // Asterisk indicates deviations from real JS. |
| 37 testExpression('var a = ""'); | 40 // Simple var test. |
| 38 // Parse and print will normalize whitespace. | 41 testExpression('var a = ""'), |
| 39 testExpression(' var a = "" ', 'var a = ""'); | 42 // Parse and print will normalize whitespace. |
| 40 // Operator precedence. | 43 testExpression(' var a = "" ', 'var a = ""'), |
| 41 testExpression('x = a + b * c'); | 44 // Operator precedence. |
| 42 testExpression('x = a * b + c'); | 45 testExpression('x = a + b * c'), |
| 43 testExpression('x = a + b * c + d'); | 46 testExpression('x = a * b + c'), |
| 44 testExpression('x = a * b + c * d'); | 47 testExpression('x = a + b * c + d'), |
| 45 testExpression('remaining = (remaining / 88) | 0', | 48 testExpression('x = a * b + c * d'), |
| 46 'remaining = remaining / 88 | 0'); | 49 testExpression('remaining = (remaining / 88) | 0', |
| 47 // Binary operators have left associativity. | 50 'remaining = remaining / 88 | 0'), |
| 48 testExpression('x = a + b + c'); | 51 // Binary operators have left associativity. |
| 49 // We can cope with relational operators and non-relational. | 52 testExpression('x = a + b + c'), |
| 50 testExpression('a + b == c + d'); | 53 // We can cope with relational operators and non-relational. |
| 51 // The prettyprinter will insert braces where needed. | 54 testExpression('a + b == c + d'), |
| 52 testExpression('a + (b == c) + d'); | 55 // The prettyprinter will insert braces where needed. |
| 53 // We can handle () for calls. | 56 testExpression('a + (b == c) + d'), |
| 54 testExpression('foo(bar)'); | 57 // We can handle () for calls. |
| 55 testExpression('foo(bar, baz)'); | 58 testExpression('foo(bar)'), |
| 56 // Chained calls without parentheses. | 59 testExpression('foo(bar, baz)'), |
| 57 testExpression('foo(bar)(baz)'); | 60 // Chained calls without parentheses. |
| 58 // Chaned calls with and without new. | 61 testExpression('foo(bar)(baz)'), |
| 59 testExpression('new foo(bar)(baz)'); | 62 // Chaned calls with and without new. |
| 60 testExpression('new foo.bar(bar)(baz)'); | 63 testExpression('new foo(bar)(baz)'), |
| 61 testExpression('foo.bar(bar)(baz)'); | 64 testExpression('new foo.bar(bar)(baz)'), |
| 62 testExpression('constructor = new Function(str)()'); | 65 testExpression('foo.bar(bar)(baz)'), |
| 63 // The prettyprinter understands chained calls without extra parentheses. | 66 testExpression('constructor = new Function(str)()'), |
| 64 testExpression('(foo(bar))(baz)', 'foo(bar)(baz)'); | 67 // The prettyprinter understands chained calls without extra parentheses. |
| 65 // Chains of dotting and calls. | 68 testExpression('(foo(bar))(baz)', 'foo(bar)(baz)'), |
| 66 testExpression('foo.bar(baz)'); | 69 // Chains of dotting and calls. |
| 67 // String literal. | 70 testExpression('foo.bar(baz)'), |
| 68 testExpression('var x = "fisk"'); | 71 // String literal. |
| 69 // String literal with \n. | 72 testExpression('var x = "fisk"'), |
| 70 testExpression(r'var x = "\n"'); | 73 // String literal with \n. |
| 71 // String literal with escaped quote. | 74 testExpression(r'var x = "\n"'), |
| 72 testExpression(r'var x = "\""'); | 75 // String literal with escaped quote. |
| 73 // *No clever escapes. | 76 testExpression(r'var x = "\""'), |
| 74 testError(r'var x = "\x42"', 'escapes are not allowed in literals'); | 77 // *No clever escapes. |
| 75 // Operator new. | 78 testError(r'var x = "\x42"', 'escapes are not allowed in literals'), |
| 76 testExpression('new Foo()'); | 79 // Operator new. |
| 77 // New with dotted access. | 80 testExpression('new Foo()'), |
| 78 testExpression('new Frobinator.frobinate()'); | 81 // New with dotted access. |
| 79 testExpression('new Frobinator().frobinate()'); | 82 testExpression('new Frobinator.frobinate()'), |
| 80 // The prettyprinter strips some superfluous parentheses. | 83 testExpression('new Frobinator().frobinate()'), |
| 81 testExpression('(new Frobinator()).frobinate()', | 84 // The prettyprinter strips some superfluous parentheses. |
| 82 'new Frobinator().frobinate()'); | 85 testExpression('(new Frobinator()).frobinate()', |
| 83 // *We want a bracket on 'new'. | 86 'new Frobinator().frobinate()'), |
| 84 testError('new Foo', 'Parentheses are required'); | 87 // *We want a bracket on 'new'. |
| 85 testError('(new Foo)', 'Parentheses are required'); | 88 testError('new Foo', 'Parentheses are required'), |
| 86 // Bogus operators. | 89 testError('(new Foo)', 'Parentheses are required'), |
| 87 testError('a +++ b', 'Unknown operator'); | 90 // Bogus operators. |
| 88 // This isn't perl. There are rules. | 91 testError('a +++ b', 'Unknown operator'), |
| 89 testError('a <=> b', 'Unknown operator'); | 92 // This isn't perl. There are rules. |
| 90 // Typeof. | 93 testError('a <=> b', 'Unknown operator'), |
| 91 testExpression('typeof foo == "number"'); | 94 // Typeof. |
| 92 // Strange relation. | 95 testExpression('typeof foo == "number"'), |
| 93 testExpression('a < b < c'); | 96 // Strange relation. |
| 94 // Chained var. | 97 testExpression('a < b < c'), |
| 95 testExpression('var x = 0, y = 1.2, z = 42'); | 98 // Chained var. |
| 96 // Empty object literal. | 99 testExpression('var x = 0, y = 1.2, z = 42'), |
| 97 testExpression('foo({}, {})'); | 100 // Empty object literal. |
| 98 // *Can't handle non-empty object literals | 101 testExpression('foo({}, {})'), |
| 99 testExpression('foo({meaning: 42})'); | 102 // *Can't handle non-empty object literals |
| 100 // Literals. | 103 testExpression('foo({meaning: 42})'), |
| 101 testExpression('x(false, true, null)'); | 104 // Literals. |
| 102 // *We should really throw here. | 105 testExpression('x(false, true, null)'), |
| 103 testExpression('var false = 42'); | 106 // *We should really throw here. |
| 104 testExpression('var new = 42'); | 107 testExpression('var false = 42'), |
| 105 // Bad keyword. | 108 testExpression('var new = 42'), |
| 106 testError('var typeof = 42', "Expected ALPHA"); | 109 // Bad keyword. |
| 107 // Malformed decimal/hex. | 110 testError('var typeof = 42', "Expected ALPHA"), |
| 108 testError('var x = 1.1.1', "Unparseable number"); | 111 // Malformed decimal/hex. |
| 109 testError('var x = 0xabcdefga', "Unparseable number"); | 112 testError('var x = 1.1.1', "Unparseable number"), |
| 110 testError('var x = 0xabcdef\$a', "Unparseable number"); | 113 testError('var x = 0xabcdefga', "Unparseable number"), |
| 111 testError('var x = 0x ', "Unparseable number"); | 114 testError('var x = 0xabcdef\$a', "Unparseable number"), |
| 112 // Good hex constants. | 115 testError('var x = 0x ', "Unparseable number"), |
| 113 testExpression('var x = 0xff'); | 116 // Good hex constants. |
| 114 testExpression('var x = 0xff + 0xff'); | 117 testExpression('var x = 0xff'), |
| 115 testExpression('var x = 0xaF + 0x0123456789abcdefABCDEF'); | 118 testExpression('var x = 0xff + 0xff'), |
| 116 // All sorts of keywords are allowed as property names in ES5. | 119 testExpression('var x = 0xaF + 0x0123456789abcdefABCDEF'), |
| 117 testExpression('x.new = 0'); | 120 // All sorts of keywords are allowed as property names in ES5. |
| 118 testExpression('x.delete = 0'); | 121 testExpression('x.new = 0'), |
| 119 testExpression('x.for = 0'); | 122 testExpression('x.delete = 0'), |
| 120 testExpression('x.instanceof = 0'); | 123 testExpression('x.for = 0'), |
| 121 testExpression('x.in = 0'); | 124 testExpression('x.instanceof = 0'), |
| 122 testExpression('x.void = 0'); | 125 testExpression('x.in = 0'), |
| 123 testExpression('x.continue = 0'); | 126 testExpression('x.void = 0'), |
| 124 // More unary. | 127 testExpression('x.continue = 0'), |
| 125 testExpression('x = !x'); | 128 // More unary. |
| 126 testExpression('!x == false'); | 129 testExpression('x = !x'), |
| 127 testExpression('var foo = void 0'); | 130 testExpression('!x == false'), |
| 128 testExpression('delete foo.bar'); | 131 testExpression('var foo = void 0'), |
| 129 testExpression('delete foo'); | 132 testExpression('delete foo.bar'), |
| 130 testExpression('x in y'); | 133 testExpression('delete foo'), |
| 131 testExpression('x instanceof y'); | 134 testExpression('x in y'), |
| 132 testExpression('a * b in c * d'); | 135 testExpression('x instanceof y'), |
| 133 testExpression('a * b instanceof c * d'); | 136 testExpression('a * b in c * d'), |
| 134 testError('x typeof y', 'Unparsed junk'); | 137 testExpression('a * b instanceof c * d'), |
| 135 testExpression('x &= ~mask'); | 138 testError('x typeof y', 'Unparsed junk'), |
| 136 // Adjacent tokens. | 139 testExpression('x &= ~mask'), |
| 137 testExpression('foo[x[bar]]'); | 140 // Adjacent tokens. |
| 138 testExpression('foo[[bar]]'); | 141 testExpression('foo[x[bar]]'), |
| 139 // Prefix ++ etc. | 142 testExpression('foo[[bar]]'), |
| 140 testExpression("++x"); | 143 // Prefix ++ etc. |
| 141 testExpression("++foo.bar"); | 144 testExpression("++x"), |
| 142 testExpression("+x"); | 145 testExpression("++foo.bar"), |
| 143 testExpression("+foo.bar"); | 146 testExpression("+x"), |
| 144 testExpression("-x"); | 147 testExpression("+foo.bar"), |
| 145 testExpression("-foo.bar"); | 148 testExpression("-x"), |
| 146 testExpression("--x"); | 149 testExpression("-foo.bar"), |
| 147 testExpression("--foo.bar"); | 150 testExpression("--x"), |
| 148 // Postfix ++ etc. | 151 testExpression("--foo.bar"), |
| 149 testExpression("x++"); | 152 // Postfix ++ etc. |
| 150 testExpression("foo.bar++"); | 153 testExpression("x++"), |
| 151 testExpression("x--"); | 154 testExpression("foo.bar++"), |
| 152 testExpression("foo.bar--"); | 155 testExpression("x--"), |
| 153 // Both! | 156 testExpression("foo.bar--"), |
| 154 testExpression("++x++"); | 157 // Both! |
| 155 testExpression("++foo.bar++"); | 158 testExpression("++x++"), |
| 156 testExpression("--x--"); | 159 testExpression("++foo.bar++"), |
| 157 testExpression("--foo.bar--"); | 160 testExpression("--x--"), |
| 158 // *We can't handle stacked unary operators (apart from !). | 161 testExpression("--foo.bar--"), |
| 159 testError("x++ ++"); | 162 // *We can't handle stacked unary operators (apart from !). |
| 160 testError("++ typeof x"); | 163 testError("x++ ++"), |
| 161 testExpression(r"var $supportsProtoName = !!{}.__proto__"); | 164 testError("++ typeof x"), |
| 162 // ++ used as a binary operator. | 165 testExpression(r"var $supportsProtoName = !!{}.__proto__"), |
| 163 testError("x++ ++ 42"); | 166 // ++ used as a binary operator. |
| 164 // Shift operators. | 167 testError("x++ ++ 42"), |
| 165 testExpression("x << 5"); | 168 // Shift operators. |
| 166 testExpression("x << y + 1"); | 169 testExpression("x << 5"), |
| 167 testExpression("x <<= y + 1"); | 170 testExpression("x << y + 1"), |
| 168 // Array initializers. | 171 testExpression("x <<= y + 1"), |
| 169 testExpression("x = ['foo', 'bar', x[4]]"); | 172 // Array initializers. |
| 170 testExpression("[]"); | 173 testExpression("x = ['foo', 'bar', x[4]]"), |
| 171 testError("[42 42]"); | 174 testExpression("[]"), |
| 172 testExpression('beebop([1, 2, 3])'); | 175 testError("[42 42]"), |
| 173 // *We can't parse array literals with holes in them. | 176 testExpression('beebop([1, 2, 3])'), |
| 174 testError("[1,, 2]"); | 177 // *We can't parse array literals with holes in them. |
| 175 testError("[1,]"); | 178 testError("[1,, 2]"), |
| 176 testError("[,]"); | 179 testError("[1,]"), |
| 177 testError("[, 42]"); | 180 testError("[,]"), |
| 178 // Ternary operator. | 181 testError("[, 42]"), |
| 179 testExpression("x = a ? b : c"); | 182 // Ternary operator. |
| 180 testExpression("y = a == null ? b : a"); | 183 testExpression("x = a ? b : c"), |
| 181 testExpression("y = a == null ? b + c : a + c"); | 184 testExpression("y = a == null ? b : a"), |
| 182 testExpression("foo = a ? b : c ? d : e"); | 185 testExpression("y = a == null ? b + c : a + c"), |
| 183 testExpression("foo = a ? b ? c : d : e"); | 186 testExpression("foo = a ? b : c ? d : e"), |
| 184 testExpression("foo = (a = v) ? b = w : c = x ? d = y : e = z"); | 187 testExpression("foo = a ? b ? c : d : e"), |
| 185 testExpression("foo = (a = v) ? b = w ? c = x : d = y : e = z"); | 188 testExpression("foo = (a = v) ? b = w : c = x ? d = y : e = z"), |
| 186 // Stacked assignment. | 189 testExpression("foo = (a = v) ? b = w ? c = x : d = y : e = z"), |
| 187 testExpression("a = b = c"); | 190 // Stacked assignment. |
| 188 testExpression("var a = b = c"); | 191 testExpression("a = b = c"), |
| 192 testExpression("var a = b = c"), |
| 193 ])); |
| 189 } | 194 } |
| OLD | NEW |