OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 'dart:async'; |
6 import 'dart:convert'; | 6 import 'dart:convert'; |
7 import 'dart:io'; | 7 import 'dart:io'; |
8 | 8 |
9 import 'package:async_helper/async_helper.dart'; | 9 import 'package:async_helper/async_helper.dart'; |
10 import 'package:compiler/compiler_new.dart'; | 10 import 'package:compiler/compiler_new.dart'; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 try { | 109 try { |
110 @{2:test}throw '$EXCEPTION_MARKER'; | 110 @{2:test}throw '$EXCEPTION_MARKER'; |
111 } on String catch (e) { | 111 } on String catch (e) { |
112 rethrow; | 112 rethrow; |
113 } | 113 } |
114 } | 114 } |
115 ''', | 115 ''', |
116 ''' | 116 ''' |
117 import 'package:expect/expect.dart'; | 117 import 'package:expect/expect.dart'; |
118 main() { | 118 main() { |
119 test(); // This call is no longer on the stack when the error is thrown. | 119 // This call is no longer on the stack when the error is thrown. |
| 120 @{:main}test(); |
120 } | 121 } |
121 @NoInline() | 122 @NoInline() |
122 test() async { | 123 test() async { |
123 @{1:test}throw '$EXCEPTION_MARKER'; | 124 @{1:test}throw '$EXCEPTION_MARKER'; |
124 } | 125 } |
125 ''', | 126 ''', |
126 ''' | 127 ''' |
127 import 'package:expect/expect.dart'; | 128 import 'package:expect/expect.dart'; |
128 main() { | 129 main() { |
129 test1(); | 130 test1(); |
130 } | 131 } |
131 @NoInline() | 132 @NoInline() |
132 test1() async { | 133 test1() async { |
133 // This call is no longer on the stack when the error is thrown. | 134 // This call is no longer on the stack when the error is thrown. |
134 await test2(); | 135 await @{:test1}test2(); |
135 } | 136 } |
136 @NoInline() | 137 @NoInline() |
137 test2() async { | 138 test2() async { |
138 @{1:test2}throw '$EXCEPTION_MARKER'; | 139 @{1:test2}throw '$EXCEPTION_MARKER'; |
139 } | 140 } |
140 ''', | 141 ''', |
141 ''' | 142 ''' |
142 import 'package:expect/expect.dart'; | 143 import 'package:expect/expect.dart'; |
143 main() { | 144 main() { |
144 test1(); | 145 test1(); |
145 } | 146 } |
146 @NoInline() | 147 @NoInline() |
147 test1() async { | 148 test1() async { |
148 @{1:test1}test2(); | 149 @{1:test1}test2(); |
149 } | 150 } |
150 @NoInline() | 151 @NoInline() |
151 test2() { | 152 test2() { |
152 @{2:test2}throw '$EXCEPTION_MARKER'; | 153 @{2:test2}throw '$EXCEPTION_MARKER'; |
153 } | 154 } |
154 ''', | 155 ''', |
| 156 ''' |
| 157 import 'package:expect/expect.dart'; |
| 158 main() { |
| 159 // This call is no longer on the stack when the error is thrown. |
| 160 @{:main}test(); |
| 161 } |
| 162 test() async { |
| 163 var c = @{1:test}new Class(); |
| 164 } |
| 165 class Class { |
| 166 @NoInline() |
| 167 Class() { |
| 168 @{2:Class}throw '$EXCEPTION_MARKER'; |
| 169 } |
| 170 } |
| 171 ''', |
155 ]; | 172 ]; |
156 | 173 |
157 class Test { | 174 class Test { |
158 final String code; | 175 final String code; |
159 final List<StackTraceLine> expectedLines; | 176 final List<StackTraceLine> expectedLines; |
| 177 final List<StackTraceLine> unexpectedLines; |
160 | 178 |
161 Test(this.code, this.expectedLines); | 179 Test(this.code, this.expectedLines, this.unexpectedLines); |
162 } | 180 } |
163 | 181 |
164 const int _LF = 0x0A; | 182 const int _LF = 0x0A; |
165 const int _CR = 0x0D; | 183 const int _CR = 0x0D; |
166 const int _LBRACE = 0x7B; | 184 const int _LBRACE = 0x7B; |
167 | 185 |
168 Test processTestCode(String code) { | 186 Test processTestCode(String code) { |
169 StringBuffer codeBuffer = new StringBuffer(); | 187 StringBuffer codeBuffer = new StringBuffer(); |
170 Map<int, StackTraceLine> stackTraceMap = <int, StackTraceLine>{}; | 188 Map<int, StackTraceLine> stackTraceMap = <int, StackTraceLine>{}; |
| 189 List<StackTraceLine> unexpectedLines = <StackTraceLine>[]; |
171 int index = 0; | 190 int index = 0; |
172 int lineNo = 1; | 191 int lineNo = 1; |
173 int columnNo = 1; | 192 int columnNo = 1; |
174 while (index < code.length) { | 193 while (index < code.length) { |
175 int charCode = code.codeUnitAt(index); | 194 int charCode = code.codeUnitAt(index); |
176 switch (charCode) { | 195 switch (charCode) { |
177 case _LF: | 196 case _LF: |
178 codeBuffer.write('\n'); | 197 codeBuffer.write('\n'); |
179 lineNo++; | 198 lineNo++; |
180 columnNo = 1; | 199 columnNo = 1; |
181 break; | 200 break; |
182 case _CR: | 201 case _CR: |
183 if (index + 1 < code.length && code.codeUnitAt(index + 1) == _LF) { | 202 if (index + 1 < code.length && code.codeUnitAt(index + 1) == _LF) { |
184 index++; | 203 index++; |
185 } | 204 } |
186 codeBuffer.write('\n'); | 205 codeBuffer.write('\n'); |
187 lineNo++; | 206 lineNo++; |
188 columnNo = 1; | 207 columnNo = 1; |
189 break; | 208 break; |
190 case 0x40: | 209 case 0x40: |
191 if (index + 1 < code.length && code.codeUnitAt(index + 1) == _LBRACE) { | 210 if (index + 1 < code.length && code.codeUnitAt(index + 1) == _LBRACE) { |
192 int colonIndex = code.indexOf(':', index); | 211 int colonIndex = code.indexOf(':', index); |
193 int endIndex = code.indexOf('}', index); | 212 int endIndex = code.indexOf('}', index); |
194 int stackTraceIndex = | |
195 int.parse(code.substring(index + 2, colonIndex)); | |
196 String methodName = code.substring(colonIndex + 1, endIndex); | 213 String methodName = code.substring(colonIndex + 1, endIndex); |
197 assert(!stackTraceMap.containsKey(stackTraceIndex)); | 214 String indexText = code.substring(index + 2, colonIndex); |
198 stackTraceMap[stackTraceIndex] = | 215 StackTraceLine stackTraceLine = |
199 new StackTraceLine(methodName, INPUT_FILE_NAME, lineNo, columnNo); | 216 new StackTraceLine(methodName, INPUT_FILE_NAME, lineNo, columnNo); |
| 217 if (indexText == '') { |
| 218 unexpectedLines.add(stackTraceLine); |
| 219 } else { |
| 220 int stackTraceIndex = int.parse(indexText); |
| 221 assert(!stackTraceMap.containsKey(stackTraceIndex)); |
| 222 stackTraceMap[stackTraceIndex] = stackTraceLine; |
| 223 } |
200 index = endIndex; | 224 index = endIndex; |
201 } else { | 225 } else { |
202 codeBuffer.writeCharCode(charCode); | 226 codeBuffer.writeCharCode(charCode); |
203 columnNo++; | 227 columnNo++; |
204 } | 228 } |
205 break; | 229 break; |
206 default: | 230 default: |
207 codeBuffer.writeCharCode(charCode); | 231 codeBuffer.writeCharCode(charCode); |
208 columnNo++; | 232 columnNo++; |
209 } | 233 } |
210 index++; | 234 index++; |
211 } | 235 } |
212 List<StackTraceLine> expectedLines = <StackTraceLine>[]; | 236 List<StackTraceLine> expectedLines = <StackTraceLine>[]; |
213 for (int stackTraceIndex in (stackTraceMap.keys.toList()..sort()).reversed) { | 237 for (int stackTraceIndex in (stackTraceMap.keys.toList()..sort()).reversed) { |
214 expectedLines.add(stackTraceMap[stackTraceIndex]); | 238 expectedLines.add(stackTraceMap[stackTraceIndex]); |
215 } | 239 } |
216 return new Test(codeBuffer.toString(), expectedLines); | 240 return new Test(codeBuffer.toString(), expectedLines, unexpectedLines); |
217 } | 241 } |
218 | 242 |
219 void main(List<String> arguments) { | 243 void main(List<String> arguments) { |
| 244 bool verbose = false; |
| 245 bool printJs = false; |
| 246 List<int> indices; |
| 247 for (String arg in arguments) { |
| 248 if (arg == '-v') { |
| 249 verbose = true; |
| 250 } else if (arg == '--print-js') { |
| 251 printJs = true; |
| 252 } else { |
| 253 int index = int.parse(arg, onError: (_) => null); |
| 254 if (index != null) { |
| 255 indices ??= <int>[]; |
| 256 if (index < 0 || index >= TESTS.length) { |
| 257 print('Index $index out of bounds: [0;${TESTS.length - 1}]'); |
| 258 } else { |
| 259 indices.add(index); |
| 260 } |
| 261 } |
| 262 } |
| 263 } |
| 264 if (indices == null) { |
| 265 indices = new List<int>.generate(TESTS.length, (i) => i); |
| 266 } |
220 asyncTest(() async { | 267 asyncTest(() async { |
221 for (String code in TESTS) { | 268 for (int index in indices) { |
222 await runTest(processTestCode(code), verbose: arguments.contains('-v')); | 269 await runTest(index, processTestCode(TESTS[index]), |
| 270 printJs: printJs, verbose: verbose); |
223 } | 271 } |
224 }); | 272 }); |
225 } | 273 } |
226 | 274 |
227 Future runTest(Test test, {bool verbose: false}) async { | 275 Future runTest(int index, Test test, |
| 276 {bool printJs: false, bool verbose: false}) async { |
228 Directory tmpDir = await createTempDir(); | 277 Directory tmpDir = await createTempDir(); |
229 String input = '${tmpDir.path}/$INPUT_FILE_NAME'; | 278 String input = '${tmpDir.path}/$INPUT_FILE_NAME'; |
230 new File(input).writeAsStringSync(test.code); | 279 new File(input).writeAsStringSync(test.code); |
231 String output = '${tmpDir.path}/out.js'; | 280 String output = '${tmpDir.path}/out.js'; |
232 List<String> arguments = [ | 281 List<String> arguments = [ |
233 '-o$output', | 282 '-o$output', |
234 '--library-root=sdk', | 283 '--library-root=sdk', |
235 '--packages=${Platform.packageConfig}', | 284 '--packages=${Platform.packageConfig}', |
236 Flags.useNewSourceInfo, | 285 Flags.useNewSourceInfo, |
237 input, | 286 input, |
238 ]; | 287 ]; |
239 print("--------------------------------------------------------------------"); | 288 print("--$index------------------------------------------------------------"); |
240 print("Compiling dart2js ${arguments.join(' ')}\n${test.code}"); | 289 print("Compiling dart2js ${arguments.join(' ')}\n${test.code}"); |
241 CompilationResult compilationResult = await entry.internalMain(arguments); | 290 CompilationResult compilationResult = await entry.internalMain(arguments); |
242 Expect.isTrue(compilationResult.isSuccess, | 291 Expect.isTrue(compilationResult.isSuccess, |
243 "Unsuccessful compilation of test:\n${test.code}"); | 292 "Unsuccessful compilation of test:\n${test.code}"); |
244 CompilerImpl compiler = compilationResult.compiler; | 293 CompilerImpl compiler = compilationResult.compiler; |
245 SingleMapping sourceMap = new SingleMapping.fromJson( | 294 SingleMapping sourceMap = new SingleMapping.fromJson( |
246 JSON.decode(new File('$output.map').readAsStringSync())); | 295 JSON.decode(new File('$output.map').readAsStringSync())); |
247 | 296 |
| 297 if (printJs) { |
| 298 print('JavaScript output:'); |
| 299 print(new File(output).readAsStringSync()); |
| 300 } |
248 print("Running d8 $output"); | 301 print("Running d8 $output"); |
249 ProcessResult runResult = Process.runSync(d8executable, | 302 ProcessResult runResult = Process.runSync(d8executable, |
250 ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]); | 303 ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]); |
251 String out = '${runResult.stderr}\n${runResult.stdout}'; | 304 String out = '${runResult.stderr}\n${runResult.stdout}'; |
252 if (verbose) { | 305 if (verbose) { |
253 print('d8 output:'); | 306 print('d8 output:'); |
254 print(out); | 307 print(out); |
255 } | 308 } |
256 List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)')); | 309 List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)')); |
257 List<StackTraceLine> jsStackTrace = <StackTraceLine>[]; | 310 List<StackTraceLine> jsStackTrace = <StackTraceLine>[]; |
(...skipping 23 matching lines...) Expand all Loading... |
281 String fileName; | 334 String fileName; |
282 if (targetEntry.sourceUrlId != 0) { | 335 if (targetEntry.sourceUrlId != 0) { |
283 fileName = sourceMap.urls[targetEntry.sourceUrlId]; | 336 fileName = sourceMap.urls[targetEntry.sourceUrlId]; |
284 } | 337 } |
285 dartStackTrace.add(new StackTraceLine(methodName, fileName, | 338 dartStackTrace.add(new StackTraceLine(methodName, fileName, |
286 targetEntry.sourceLine + 1, targetEntry.sourceColumn + 1)); | 339 targetEntry.sourceLine + 1, targetEntry.sourceColumn + 1)); |
287 } | 340 } |
288 } | 341 } |
289 | 342 |
290 int expectedIndex = 0; | 343 int expectedIndex = 0; |
| 344 List<StackTraceLine> unexpectedLines = <StackTraceLine>[]; |
291 for (StackTraceLine line in dartStackTrace) { | 345 for (StackTraceLine line in dartStackTrace) { |
292 if (expectedIndex < test.expectedLines.length) { | 346 if (expectedIndex < test.expectedLines.length) { |
293 StackTraceLine expectedLine = test.expectedLines[expectedIndex]; | 347 StackTraceLine expectedLine = test.expectedLines[expectedIndex]; |
294 if (line.methodName == expectedLine.methodName && | 348 if (line.methodName == expectedLine.methodName && |
295 line.lineNo == expectedLine.lineNo && | 349 line.lineNo == expectedLine.lineNo && |
296 line.columnNo == expectedLine.columnNo) { | 350 line.columnNo == expectedLine.columnNo) { |
297 expectedIndex++; | 351 expectedIndex++; |
298 } | 352 } |
299 } | 353 } |
| 354 for (StackTraceLine unexpectedLine in test.unexpectedLines) { |
| 355 if (line.methodName == unexpectedLine.methodName && |
| 356 line.lineNo == unexpectedLine.lineNo && |
| 357 line.columnNo == unexpectedLine.columnNo) { |
| 358 unexpectedLines.add(line); |
| 359 } |
| 360 } |
300 } | 361 } |
301 if (verbose) { | 362 if (verbose) { |
302 print('JavaScript stacktrace:'); | 363 print('JavaScript stacktrace:'); |
303 print(jsStackTrace.join('\n')); | 364 print(jsStackTrace.join('\n')); |
304 print('Dart stacktrace:'); | 365 print('Dart stacktrace:'); |
305 print(dartStackTrace.join('\n')); | 366 print(dartStackTrace.join('\n')); |
306 } | 367 } |
307 Expect.equals( | 368 Expect.equals( |
308 expectedIndex, | 369 expectedIndex, |
309 test.expectedLines.length, | 370 test.expectedLines.length, |
310 "Missing stack trace lines for test:\n${test.code}\n" | 371 "Missing stack trace lines for test:\n${test.code}\n" |
311 "Actual:\n${dartStackTrace.join('\n')}\n" | 372 "Actual:\n${dartStackTrace.join('\n')}\n" |
312 "Expected:\n${test.expectedLines.join('\n')}\n"); | 373 "Expected:\n${test.expectedLines.join('\n')}\n"); |
| 374 Expect.isTrue( |
| 375 unexpectedLines.isEmpty, |
| 376 "Unexpected stack trace lines for test:\n${test.code}\n" |
| 377 "Actual:\n${dartStackTrace.join('\n')}\n" |
| 378 "Unexpected:\n${test.unexpectedLines.join('\n')}\n"); |
313 | 379 |
314 print("Deleting '${tmpDir.path}'."); | 380 print("Deleting '${tmpDir.path}'."); |
315 tmpDir.deleteSync(recursive: true); | 381 tmpDir.deleteSync(recursive: true); |
316 } | 382 } |
317 | 383 |
318 class StackTraceLine { | 384 class StackTraceLine { |
319 String methodName; | 385 String methodName; |
320 String fileName; | 386 String fileName; |
321 int lineNo; | 387 int lineNo; |
322 int columnNo; | 388 int columnNo; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 String get d8executable { | 495 String get d8executable { |
430 if (Platform.isWindows) { | 496 if (Platform.isWindows) { |
431 return 'third_party/d8/windows/d8.exe'; | 497 return 'third_party/d8/windows/d8.exe'; |
432 } else if (Platform.isLinux) { | 498 } else if (Platform.isLinux) { |
433 return 'third_party/d8/linux/d8'; | 499 return 'third_party/d8/linux/d8'; |
434 } else if (Platform.isMacOS) { | 500 } else if (Platform.isMacOS) { |
435 return 'third_party/d8/macos/d8'; | 501 return 'third_party/d8/macos/d8'; |
436 } | 502 } |
437 throw new UnsupportedError('Unsupported platform.'); | 503 throw new UnsupportedError('Unsupported platform.'); |
438 } | 504 } |
OLD | NEW |