OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library test_helper; | 5 library test_helper; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 import 'package:observatory/service_io.dart'; | 10 import 'package:observatory/service_io.dart'; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 final List<String> args; | 83 final List<String> args; |
84 bool killedByTester = false; | 84 bool killedByTester = false; |
85 | 85 |
86 _ServiceTesteeLauncher() : | 86 _ServiceTesteeLauncher() : |
87 args = [Platform.script.toFilePath()] {} | 87 args = [Platform.script.toFilePath()] {} |
88 | 88 |
89 // Spawn the testee process. | 89 // Spawn the testee process. |
90 Future<Process> _spawnProcess(bool pause_on_start, | 90 Future<Process> _spawnProcess(bool pause_on_start, |
91 bool pause_on_exit, | 91 bool pause_on_exit, |
92 bool pause_on_unhandled_exceptions, | 92 bool pause_on_unhandled_exceptions, |
93 bool trace_service, | |
94 bool trace_compiler, | |
95 bool testeeControlsServer, | 93 bool testeeControlsServer, |
96 bool useAuthToken) { | 94 bool useAuthToken, |
| 95 List<String> extraArgs) { |
97 assert(pause_on_start != null); | 96 assert(pause_on_start != null); |
98 assert(pause_on_exit != null); | 97 assert(pause_on_exit != null); |
99 assert(pause_on_unhandled_exceptions != null); | 98 assert(pause_on_unhandled_exceptions != null); |
100 assert(trace_service != null); | |
101 assert(trace_compiler != null); | |
102 assert(testeeControlsServer != null); | 99 assert(testeeControlsServer != null); |
103 assert(useAuthToken != null); | 100 assert(useAuthToken != null); |
104 | 101 |
105 if (_shouldLaunchSkyShell()) { | 102 if (_shouldLaunchSkyShell()) { |
106 return _spawnSkyProcess(pause_on_start, | 103 return _spawnSkyProcess(pause_on_start, |
107 pause_on_exit, | 104 pause_on_exit, |
108 pause_on_unhandled_exceptions, | 105 pause_on_unhandled_exceptions, |
109 trace_service, | 106 testeeControlsServer, |
110 trace_compiler, | 107 extraArgs); |
111 testeeControlsServer); | |
112 } else { | 108 } else { |
113 return _spawnDartProcess(pause_on_start, | 109 return _spawnDartProcess(pause_on_start, |
114 pause_on_exit, | 110 pause_on_exit, |
115 pause_on_unhandled_exceptions, | 111 pause_on_unhandled_exceptions, |
116 trace_service, | |
117 trace_compiler, | |
118 testeeControlsServer, | 112 testeeControlsServer, |
119 useAuthToken); | 113 useAuthToken, |
| 114 extraArgs); |
120 } | 115 } |
121 } | 116 } |
122 | 117 |
123 Future<Process> _spawnDartProcess(bool pause_on_start, | 118 Future<Process> _spawnDartProcess(bool pause_on_start, |
124 bool pause_on_exit, | 119 bool pause_on_exit, |
125 bool pause_on_unhandled_exceptions, | 120 bool pause_on_unhandled_exceptions, |
126 bool trace_service, | |
127 bool trace_compiler, | |
128 bool testeeControlsServer, | 121 bool testeeControlsServer, |
129 bool useAuthToken) { | 122 bool useAuthToken, |
| 123 List<String> extraArgs) { |
130 assert(!_shouldLaunchSkyShell()); | 124 assert(!_shouldLaunchSkyShell()); |
131 | 125 |
132 String dartExecutable = Platform.executable; | 126 String dartExecutable = Platform.executable; |
133 | 127 |
134 var fullArgs = []; | 128 var fullArgs = []; |
135 if (trace_service) { | |
136 fullArgs.add('--trace-service'); | |
137 fullArgs.add('--trace-service-verbose'); | |
138 } | |
139 if (trace_compiler) { | |
140 fullArgs.add('--trace-compiler'); | |
141 } | |
142 if (pause_on_start) { | 129 if (pause_on_start) { |
143 fullArgs.add('--pause-isolates-on-start'); | 130 fullArgs.add('--pause-isolates-on-start'); |
144 } | 131 } |
145 if (pause_on_exit) { | 132 if (pause_on_exit) { |
146 fullArgs.add('--pause-isolates-on-exit'); | 133 fullArgs.add('--pause-isolates-on-exit'); |
147 } | 134 } |
148 if (pause_on_unhandled_exceptions) { | 135 if (pause_on_unhandled_exceptions) { |
149 fullArgs.add('--pause-isolates-on-unhandled-exceptions'); | 136 fullArgs.add('--pause-isolates-on-unhandled-exceptions'); |
150 } | 137 } |
| 138 if (extraArgs != null) { |
| 139 fullArgs.addAll(extraArgs); |
| 140 } |
151 | 141 |
152 fullArgs.addAll(Platform.executableArguments); | 142 fullArgs.addAll(Platform.executableArguments); |
153 if (!testeeControlsServer) { | 143 if (!testeeControlsServer) { |
154 fullArgs.add('--enable-vm-service:0'); | 144 fullArgs.add('--enable-vm-service:0'); |
155 } | 145 } |
156 fullArgs.addAll(args); | 146 fullArgs.addAll(args); |
157 | 147 |
158 return _spawnCommon( | 148 return _spawnCommon( |
159 dartExecutable, | 149 dartExecutable, |
160 fullArgs, | 150 fullArgs, |
161 <String, String>{ | 151 <String, String>{ |
162 'DART_SERVICE_USE_AUTH': '$useAuthToken' | 152 'DART_SERVICE_USE_AUTH': '$useAuthToken' |
163 }); | 153 }); |
164 } | 154 } |
165 | 155 |
166 Future<Process> _spawnSkyProcess(bool pause_on_start, | 156 Future<Process> _spawnSkyProcess(bool pause_on_start, |
167 bool pause_on_exit, | 157 bool pause_on_exit, |
168 bool pause_on_unhandled_exceptions, | 158 bool pause_on_unhandled_exceptions, |
169 bool trace_service, | 159 bool testeeControlsServer, |
170 bool trace_compiler, | 160 List<String> extraArgs) { |
171 bool testeeControlsServer) { | |
172 assert(_shouldLaunchSkyShell()); | 161 assert(_shouldLaunchSkyShell()); |
173 | 162 |
174 String dartExecutable = _skyShellPath(); | 163 String dartExecutable = _skyShellPath(); |
175 | 164 |
176 var dartFlags = []; | 165 var dartFlags = []; |
177 var fullArgs = []; | 166 var fullArgs = []; |
178 if (trace_service) { | |
179 dartFlags.add('--trace_service'); | |
180 dartFlags.add('--trace_service_verbose'); | |
181 } | |
182 if (trace_compiler) { | |
183 dartFlags.add('--trace_compiler'); | |
184 } | |
185 if (pause_on_start) { | 167 if (pause_on_start) { |
186 dartFlags.add('--pause_isolates_on_start'); | 168 dartFlags.add('--pause_isolates_on_start'); |
187 fullArgs.add('--start-paused'); | 169 fullArgs.add('--start-paused'); |
188 } | 170 } |
189 if (pause_on_exit) { | 171 if (pause_on_exit) { |
190 dartFlags.add('--pause_isolates_on_exit'); | 172 dartFlags.add('--pause_isolates_on_exit'); |
191 } | 173 } |
192 if (pause_on_unhandled_exceptions) { | 174 if (pause_on_unhandled_exceptions) { |
193 dartFlags.add('--pause_isolates_on_unhandled_exceptions'); | 175 dartFlags.add('--pause_isolates_on_unhandled_exceptions'); |
194 } | 176 } |
195 // Override mirrors. | 177 // Override mirrors. |
196 dartFlags.add('--enable_mirrors=true'); | 178 dartFlags.add('--enable_mirrors=true'); |
| 179 if (extraArgs != null) { |
| 180 fullArgs.addAll(extraArgs); |
| 181 } |
197 | 182 |
198 fullArgs.addAll(Platform.executableArguments); | 183 fullArgs.addAll(Platform.executableArguments); |
199 if (!testeeControlsServer) { | 184 if (!testeeControlsServer) { |
200 fullArgs.add('--observatory-port=0'); | 185 fullArgs.add('--observatory-port=0'); |
201 } | 186 } |
202 fullArgs.add('--dart-flags=${dartFlags.join(' ')}'); | 187 fullArgs.add('--dart-flags=${dartFlags.join(' ')}'); |
203 fullArgs.addAll(args); | 188 fullArgs.addAll(args); |
204 | 189 |
205 return _spawnCommon(dartExecutable, fullArgs, <String, String>{}); | 190 return _spawnCommon(dartExecutable, fullArgs, <String, String>{}); |
206 } | 191 } |
207 | 192 |
208 Future<Process> _spawnCommon(String executable, | 193 Future<Process> _spawnCommon(String executable, |
209 List<String> arguments, | 194 List<String> arguments, |
210 Map<String, String> dartEnvironment) { | 195 Map<String, String> dartEnvironment) { |
211 var environment = _TESTEE_SPAWN_ENV; | 196 var environment = _TESTEE_SPAWN_ENV; |
212 var bashEnvironment = new StringBuffer(); | 197 var bashEnvironment = new StringBuffer(); |
213 environment.forEach((k, v) => bashEnvironment.write("$k=$v ")); | 198 environment.forEach((k, v) => bashEnvironment.write("$k=$v ")); |
214 if (dartEnvironment != null) { | 199 if (dartEnvironment != null) { |
215 dartEnvironment.forEach((k, v) { | 200 dartEnvironment.forEach((k, v) { |
216 arguments.insert(0, '-D$k=$v'); | 201 arguments.insert(0, '-D$k=$v'); |
217 }); | 202 }); |
218 } | 203 } |
219 print('** Launching $bashEnvironment$executable ${arguments.join(' ')}'); | 204 print('** Launching $bashEnvironment$executable ${arguments.join(' ')}'); |
220 return Process.start(executable, arguments, environment: environment); | 205 return Process.start(executable, arguments, environment: environment); |
221 } | 206 } |
222 | 207 |
223 Future<Uri> launch(bool pause_on_start, | 208 Future<Uri> launch(bool pause_on_start, |
224 bool pause_on_exit, | 209 bool pause_on_exit, |
225 bool pause_on_unhandled_exceptions, | 210 bool pause_on_unhandled_exceptions, |
226 bool trace_service, | |
227 bool trace_compiler, | |
228 bool testeeControlsServer, | 211 bool testeeControlsServer, |
229 bool useAuthToken) { | 212 bool useAuthToken, |
| 213 List<String> extraArgs) { |
230 return _spawnProcess(pause_on_start, | 214 return _spawnProcess(pause_on_start, |
231 pause_on_exit, | 215 pause_on_exit, |
232 pause_on_unhandled_exceptions, | 216 pause_on_unhandled_exceptions, |
233 trace_service, | |
234 trace_compiler, | |
235 testeeControlsServer, | 217 testeeControlsServer, |
236 useAuthToken).then((p) { | 218 useAuthToken, |
| 219 extraArgs).then((p) { |
237 Completer<Uri> completer = new Completer<Uri>(); | 220 Completer<Uri> completer = new Completer<Uri>(); |
238 process = p; | 221 process = p; |
239 Uri uri; | 222 Uri uri; |
240 var blank; | 223 var blank; |
241 var first = true; | 224 var first = true; |
242 process.stdout.transform(UTF8.decoder) | 225 process.stdout.transform(UTF8.decoder) |
243 .transform(new LineSplitter()).listen((line) { | 226 .transform(new LineSplitter()).listen((line) { |
244 const kObservatoryListening = 'Observatory listening on '; | 227 const kObservatoryListening = 'Observatory listening on '; |
245 if (line.startsWith(kObservatoryListening)) { | 228 if (line.startsWith(kObservatoryListening)) { |
246 uri = Uri.parse(line.substring(kObservatoryListening.length)); | 229 uri = Uri.parse(line.substring(kObservatoryListening.length)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 | 264 |
282 void setupAddresses(Uri serverAddress) { | 265 void setupAddresses(Uri serverAddress) { |
283 serviceWebsocketAddress = | 266 serviceWebsocketAddress = |
284 'ws://${serverAddress.authority}${serverAddress.path}ws'; | 267 'ws://${serverAddress.authority}${serverAddress.path}ws'; |
285 serviceHttpAddress = | 268 serviceHttpAddress = |
286 'http://${serverAddress.authority}${serverAddress.path}'; | 269 'http://${serverAddress.authority}${serverAddress.path}'; |
287 } | 270 } |
288 | 271 |
289 class _ServiceTesterRunner { | 272 class _ServiceTesterRunner { |
290 void run({List<String> mainArgs, | 273 void run({List<String> mainArgs, |
| 274 List<String> extraArgs, |
291 List<VMTest> vmTests, | 275 List<VMTest> vmTests, |
292 List<IsolateTest> isolateTests, | 276 List<IsolateTest> isolateTests, |
293 bool pause_on_start: false, | 277 bool pause_on_start: false, |
294 bool pause_on_exit: false, | 278 bool pause_on_exit: false, |
295 bool trace_service: false, | |
296 bool trace_compiler: false, | |
297 bool verbose_vm: false, | 279 bool verbose_vm: false, |
298 bool pause_on_unhandled_exceptions: false, | 280 bool pause_on_unhandled_exceptions: false, |
299 bool testeeControlsServer: false, | 281 bool testeeControlsServer: false, |
300 bool useAuthToken: false}) { | 282 bool useAuthToken: false}) { |
301 var process = new _ServiceTesteeLauncher(); | 283 var process = new _ServiceTesteeLauncher(); |
302 process.launch(pause_on_start, pause_on_exit, | 284 process.launch(pause_on_start, pause_on_exit, |
303 pause_on_unhandled_exceptions, | 285 pause_on_unhandled_exceptions, |
304 trace_service, trace_compiler, | |
305 testeeControlsServer, | 286 testeeControlsServer, |
306 useAuthToken).then((Uri serverAddress) async { | 287 useAuthToken, extraArgs).then((Uri serverAddress) async { |
307 if (mainArgs.contains("--gdb")) { | 288 if (mainArgs.contains("--gdb")) { |
308 var pid = process.process.pid; | 289 var pid = process.process.pid; |
309 var wait = new Duration(seconds: 10); | 290 var wait = new Duration(seconds: 10); |
310 print("Testee has pid $pid, waiting $wait before continuing"); | 291 print("Testee has pid $pid, waiting $wait before continuing"); |
311 sleep(wait); | 292 sleep(wait); |
312 } | 293 } |
313 setupAddresses(serverAddress); | 294 setupAddresses(serverAddress); |
314 var name = Platform.script.pathSegments.last; | 295 var name = Platform.script.pathSegments.last; |
315 Chain.capture(() async { | 296 Chain.capture(() async { |
316 var vm = | 297 var vm = |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 /// Runs [tests] in sequence, each of which should take an [Isolate] and | 338 /// Runs [tests] in sequence, each of which should take an [Isolate] and |
358 /// return a [Future]. Code for setting up state can run before and/or | 339 /// return a [Future]. Code for setting up state can run before and/or |
359 /// concurrently with the tests. Uses [mainArgs] to determine whether | 340 /// concurrently with the tests. Uses [mainArgs] to determine whether |
360 /// to run tests or testee in this invokation of the script. | 341 /// to run tests or testee in this invokation of the script. |
361 Future runIsolateTests(List<String> mainArgs, | 342 Future runIsolateTests(List<String> mainArgs, |
362 List<IsolateTest> tests, | 343 List<IsolateTest> tests, |
363 {testeeBefore(), | 344 {testeeBefore(), |
364 testeeConcurrent(), | 345 testeeConcurrent(), |
365 bool pause_on_start: false, | 346 bool pause_on_start: false, |
366 bool pause_on_exit: false, | 347 bool pause_on_exit: false, |
367 bool trace_service: false, | |
368 bool trace_compiler: false, | |
369 bool verbose_vm: false, | 348 bool verbose_vm: false, |
370 bool pause_on_unhandled_exceptions: false, | 349 bool pause_on_unhandled_exceptions: false, |
371 bool testeeControlsServer: false, | 350 bool testeeControlsServer: false, |
372 bool useAuthToken: false}) async { | 351 bool useAuthToken: false, |
| 352 List<String> extraArgs}) async { |
373 assert(!pause_on_start || testeeBefore == null); | 353 assert(!pause_on_start || testeeBefore == null); |
374 if (_isTestee()) { | 354 if (_isTestee()) { |
375 new _ServiceTesteeRunner().run(testeeBefore: testeeBefore, | 355 new _ServiceTesteeRunner().run(testeeBefore: testeeBefore, |
376 testeeConcurrent: testeeConcurrent, | 356 testeeConcurrent: testeeConcurrent, |
377 pause_on_start: pause_on_start, | 357 pause_on_start: pause_on_start, |
378 pause_on_exit: pause_on_exit); | 358 pause_on_exit: pause_on_exit); |
379 } else { | 359 } else { |
380 new _ServiceTesterRunner().run( | 360 new _ServiceTesterRunner().run( |
381 mainArgs: mainArgs, | 361 mainArgs: mainArgs, |
| 362 extraArgs: extraArgs, |
382 isolateTests: tests, | 363 isolateTests: tests, |
383 pause_on_start: pause_on_start, | 364 pause_on_start: pause_on_start, |
384 pause_on_exit: pause_on_exit, | 365 pause_on_exit: pause_on_exit, |
385 trace_service: trace_service, | |
386 trace_compiler: trace_compiler, | |
387 verbose_vm: verbose_vm, | 366 verbose_vm: verbose_vm, |
388 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions, | 367 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions, |
389 testeeControlsServer: testeeControlsServer, | 368 testeeControlsServer: testeeControlsServer, |
390 useAuthToken: useAuthToken); | 369 useAuthToken: useAuthToken); |
391 } | 370 } |
392 } | 371 } |
393 | 372 |
394 /// Runs [tests] in sequence, each of which should take an [Isolate] and | 373 /// Runs [tests] in sequence, each of which should take an [Isolate] and |
395 /// return a [Future]. Code for setting up state can run before and/or | 374 /// return a [Future]. Code for setting up state can run before and/or |
396 /// concurrently with the tests. Uses [mainArgs] to determine whether | 375 /// concurrently with the tests. Uses [mainArgs] to determine whether |
397 /// to run tests or testee in this invokation of the script. | 376 /// to run tests or testee in this invokation of the script. |
398 /// | 377 /// |
399 /// This is a special version of this test harness specifically for the | 378 /// This is a special version of this test harness specifically for the |
400 /// pause_on_unhandled_exceptions_test, which cannot properly function | 379 /// pause_on_unhandled_exceptions_test, which cannot properly function |
401 /// in an async context (because exceptions are *always* handled in async | 380 /// in an async context (because exceptions are *always* handled in async |
402 /// functions). | 381 /// functions). |
403 void runIsolateTestsSynchronous(List<String> mainArgs, | 382 void runIsolateTestsSynchronous(List<String> mainArgs, |
404 List<IsolateTest> tests, | 383 List<IsolateTest> tests, |
405 {void testeeBefore(), | 384 {void testeeBefore(), |
406 void testeeConcurrent(), | 385 void testeeConcurrent(), |
407 bool pause_on_start: false, | 386 bool pause_on_start: false, |
408 bool pause_on_exit: false, | 387 bool pause_on_exit: false, |
409 bool trace_service: false, | |
410 bool trace_compiler: false, | |
411 bool verbose_vm: false, | 388 bool verbose_vm: false, |
412 bool pause_on_unhandled_exceptions: false}) { | 389 bool pause_on_unhandled_exceptions: false, |
| 390 List<String> extraArgs}) { |
413 assert(!pause_on_start || testeeBefore == null); | 391 assert(!pause_on_start || testeeBefore == null); |
414 if (_isTestee()) { | 392 if (_isTestee()) { |
415 new _ServiceTesteeRunner().runSync(testeeBeforeSync: testeeBefore, | 393 new _ServiceTesteeRunner().runSync(testeeBeforeSync: testeeBefore, |
416 testeeConcurrentSync: testeeConcurrent, | 394 testeeConcurrentSync: testeeConcurrent, |
417 pause_on_start: pause_on_start, | 395 pause_on_start: pause_on_start, |
418 pause_on_exit: pause_on_exit); | 396 pause_on_exit: pause_on_exit); |
419 } else { | 397 } else { |
420 new _ServiceTesterRunner().run( | 398 new _ServiceTesterRunner().run( |
421 mainArgs: mainArgs, | 399 mainArgs: mainArgs, |
| 400 extraArgs: extraArgs, |
422 isolateTests: tests, | 401 isolateTests: tests, |
423 pause_on_start: pause_on_start, | 402 pause_on_start: pause_on_start, |
424 pause_on_exit: pause_on_exit, | 403 pause_on_exit: pause_on_exit, |
425 trace_service: trace_service, | |
426 trace_compiler: trace_compiler, | |
427 verbose_vm: verbose_vm, | 404 verbose_vm: verbose_vm, |
428 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions); | 405 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions); |
429 } | 406 } |
430 } | 407 } |
431 | 408 |
432 | 409 |
433 /// Runs [tests] in sequence, each of which should take an [Isolate] and | 410 /// Runs [tests] in sequence, each of which should take an [Isolate] and |
434 /// return a [Future]. Code for setting up state can run before and/or | 411 /// return a [Future]. Code for setting up state can run before and/or |
435 /// concurrently with the tests. Uses [mainArgs] to determine whether | 412 /// concurrently with the tests. Uses [mainArgs] to determine whether |
436 /// to run tests or testee in this invokation of the script. | 413 /// to run tests or testee in this invokation of the script. |
437 Future runVMTests(List<String> mainArgs, | 414 Future runVMTests(List<String> mainArgs, |
438 List<VMTest> tests, | 415 List<VMTest> tests, |
439 {testeeBefore(), | 416 {testeeBefore(), |
440 testeeConcurrent(), | 417 testeeConcurrent(), |
441 bool pause_on_start: false, | 418 bool pause_on_start: false, |
442 bool pause_on_exit: false, | 419 bool pause_on_exit: false, |
443 bool trace_service: false, | |
444 bool trace_compiler: false, | |
445 bool verbose_vm: false, | 420 bool verbose_vm: false, |
446 bool pause_on_unhandled_exceptions: false}) async { | 421 bool pause_on_unhandled_exceptions: false, |
| 422 List<String> extraArgs}) async { |
447 if (_isTestee()) { | 423 if (_isTestee()) { |
448 new _ServiceTesteeRunner().run(testeeBefore: testeeBefore, | 424 new _ServiceTesteeRunner().run(testeeBefore: testeeBefore, |
449 testeeConcurrent: testeeConcurrent, | 425 testeeConcurrent: testeeConcurrent, |
450 pause_on_start: pause_on_start, | 426 pause_on_start: pause_on_start, |
451 pause_on_exit: pause_on_exit); | 427 pause_on_exit: pause_on_exit); |
452 } else { | 428 } else { |
453 new _ServiceTesterRunner().run( | 429 new _ServiceTesterRunner().run( |
454 mainArgs: mainArgs, | 430 mainArgs: mainArgs, |
| 431 extraArgs: extraArgs, |
455 vmTests: tests, | 432 vmTests: tests, |
456 pause_on_start: pause_on_start, | 433 pause_on_start: pause_on_start, |
457 pause_on_exit: pause_on_exit, | 434 pause_on_exit: pause_on_exit, |
458 trace_service: trace_service, | |
459 trace_compiler: trace_compiler, | |
460 verbose_vm: verbose_vm, | 435 verbose_vm: verbose_vm, |
461 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions); | 436 pause_on_unhandled_exceptions: pause_on_unhandled_exceptions); |
462 } | 437 } |
463 } | 438 } |
OLD | NEW |