| 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 |