OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 4246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4257 v8::Context::New(isolate, &extensions); | 4257 v8::Context::New(isolate, &extensions); |
4258 } | 4258 } |
4259 // Check that no DebugBreak events occured during the context creation. | 4259 // Check that no DebugBreak events occured during the context creation. |
4260 CHECK_EQ(0, break_point_hit_count); | 4260 CHECK_EQ(0, break_point_hit_count); |
4261 | 4261 |
4262 // Get rid of the debug event listener. | 4262 // Get rid of the debug event listener. |
4263 v8::Debug::SetDebugEventListener(NULL); | 4263 v8::Debug::SetDebugEventListener(NULL); |
4264 CheckDebuggerUnloaded(); | 4264 CheckDebuggerUnloaded(); |
4265 } | 4265 } |
4266 | 4266 |
4267 static v8::Handle<v8::Array> NamedEnum(const v8::AccessorInfo&) { | 4267 static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) { |
4268 v8::Handle<v8::Array> result = v8::Array::New(3); | 4268 v8::Handle<v8::Array> result = v8::Array::New(3); |
4269 result->Set(v8::Integer::New(0), v8::String::New("a")); | 4269 result->Set(v8::Integer::New(0), v8::String::New("a")); |
4270 result->Set(v8::Integer::New(1), v8::String::New("b")); | 4270 result->Set(v8::Integer::New(1), v8::String::New("b")); |
4271 result->Set(v8::Integer::New(2), v8::String::New("c")); | 4271 result->Set(v8::Integer::New(2), v8::String::New("c")); |
4272 return result; | 4272 info.GetReturnValue().Set(result); |
4273 } | 4273 } |
4274 | 4274 |
4275 | 4275 |
4276 static v8::Handle<v8::Array> IndexedEnum(const v8::AccessorInfo&) { | 4276 static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) { |
4277 v8::Handle<v8::Array> result = v8::Array::New(2); | 4277 v8::Handle<v8::Array> result = v8::Array::New(2); |
4278 result->Set(v8::Integer::New(0), v8::Number::New(1)); | 4278 result->Set(v8::Integer::New(0), v8::Number::New(1)); |
4279 result->Set(v8::Integer::New(1), v8::Number::New(10)); | 4279 result->Set(v8::Integer::New(1), v8::Number::New(10)); |
4280 return result; | 4280 info.GetReturnValue().Set(result); |
4281 } | 4281 } |
4282 | 4282 |
4283 | 4283 |
4284 static v8::Handle<v8::Value> NamedGetter(v8::Local<v8::String> name, | 4284 static void NamedGetter(v8::Local<v8::String> name, |
4285 const v8::AccessorInfo& info) { | 4285 const v8::PropertyCallbackInfo<v8::Value>& info) { |
4286 v8::String::Utf8Value n(name); | 4286 v8::String::Utf8Value n(name); |
4287 if (strcmp(*n, "a") == 0) { | 4287 if (strcmp(*n, "a") == 0) { |
4288 return v8::String::New("AA"); | 4288 info.GetReturnValue().Set(v8::String::New("AA")); |
| 4289 return; |
4289 } else if (strcmp(*n, "b") == 0) { | 4290 } else if (strcmp(*n, "b") == 0) { |
4290 return v8::String::New("BB"); | 4291 info.GetReturnValue().Set(v8::String::New("BB")); |
| 4292 return; |
4291 } else if (strcmp(*n, "c") == 0) { | 4293 } else if (strcmp(*n, "c") == 0) { |
4292 return v8::String::New("CC"); | 4294 info.GetReturnValue().Set(v8::String::New("CC")); |
| 4295 return; |
4293 } else { | 4296 } else { |
4294 return v8::Undefined(); | 4297 info.GetReturnValue().SetUndefined(); |
| 4298 return; |
4295 } | 4299 } |
4296 | 4300 info.GetReturnValue().Set(name); |
4297 return name; | |
4298 } | 4301 } |
4299 | 4302 |
4300 | 4303 |
4301 static v8::Handle<v8::Value> IndexedGetter(uint32_t index, | 4304 static void IndexedGetter(uint32_t index, |
4302 const v8::AccessorInfo& info) { | 4305 const v8::PropertyCallbackInfo<v8::Value>& info) { |
4303 return v8::Number::New(index + 1); | 4306 info.GetReturnValue().Set(static_cast<double>(index + 1)); |
4304 } | 4307 } |
4305 | 4308 |
4306 | 4309 |
4307 TEST(InterceptorPropertyMirror) { | 4310 TEST(InterceptorPropertyMirror) { |
4308 // Create a V8 environment with debug access. | 4311 // Create a V8 environment with debug access. |
4309 DebugLocalContext env; | 4312 DebugLocalContext env; |
4310 v8::HandleScope scope(env->GetIsolate()); | 4313 v8::HandleScope scope(env->GetIsolate()); |
4311 env.ExposeDebug(); | 4314 env.ExposeDebug(); |
4312 | 4315 |
4313 // Create object with named interceptor. | 4316 // Create object with named interceptor. |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4523 "o0_mirror.property('y').value().value()")->Int32Value()); | 4526 "o0_mirror.property('y').value().value()")->Int32Value()); |
4524 CHECK_EQ(2, CompileRun( | 4527 CHECK_EQ(2, CompileRun( |
4525 "o0_mirror.property('z').value().value()")->Int32Value()); | 4528 "o0_mirror.property('z').value().value()")->Int32Value()); |
4526 CHECK(CompileRun("o0_mirror.property('u').isUndefined()")->BooleanValue()); | 4529 CHECK(CompileRun("o0_mirror.property('u').isUndefined()")->BooleanValue()); |
4527 | 4530 |
4528 // The prototype (__proto__) for o0 should be o3 as o1 and o2 are hidden. | 4531 // The prototype (__proto__) for o0 should be o3 as o1 and o2 are hidden. |
4529 CHECK(CompileRun("o0_mirror.protoObject() == o3_mirror")->BooleanValue()); | 4532 CHECK(CompileRun("o0_mirror.protoObject() == o3_mirror")->BooleanValue()); |
4530 } | 4533 } |
4531 | 4534 |
4532 | 4535 |
4533 static v8::Handle<v8::Value> ProtperyXNativeGetter( | 4536 static void ProtperyXNativeGetter( |
4534 v8::Local<v8::String> property, const v8::AccessorInfo& info) { | 4537 v8::Local<v8::String> property, |
4535 return v8::Integer::New(10); | 4538 const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 4539 info.GetReturnValue().Set(10); |
4536 } | 4540 } |
4537 | 4541 |
4538 | 4542 |
4539 TEST(NativeGetterPropertyMirror) { | 4543 TEST(NativeGetterPropertyMirror) { |
4540 // Create a V8 environment with debug access. | 4544 // Create a V8 environment with debug access. |
4541 DebugLocalContext env; | 4545 DebugLocalContext env; |
4542 v8::HandleScope scope(env->GetIsolate()); | 4546 v8::HandleScope scope(env->GetIsolate()); |
4543 env.ExposeDebug(); | 4547 env.ExposeDebug(); |
4544 | 4548 |
4545 v8::Handle<v8::String> name = v8::String::New("x"); | 4549 v8::Handle<v8::String> name = v8::String::New("x"); |
(...skipping 14 matching lines...) Expand all Loading... |
4560 CompileRun("var named_names = instance_mirror.propertyNames();"); | 4564 CompileRun("var named_names = instance_mirror.propertyNames();"); |
4561 CHECK_EQ(1, CompileRun("named_names.length")->Int32Value()); | 4565 CHECK_EQ(1, CompileRun("named_names.length")->Int32Value()); |
4562 CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue()); | 4566 CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue()); |
4563 CHECK(CompileRun( | 4567 CHECK(CompileRun( |
4564 "instance_mirror.property('x').value().isNumber()")->BooleanValue()); | 4568 "instance_mirror.property('x').value().isNumber()")->BooleanValue()); |
4565 CHECK(CompileRun( | 4569 CHECK(CompileRun( |
4566 "instance_mirror.property('x').value().value() == 10")->BooleanValue()); | 4570 "instance_mirror.property('x').value().value() == 10")->BooleanValue()); |
4567 } | 4571 } |
4568 | 4572 |
4569 | 4573 |
4570 static v8::Handle<v8::Value> ProtperyXNativeGetterThrowingError( | 4574 static void ProtperyXNativeGetterThrowingError( |
4571 v8::Local<v8::String> property, const v8::AccessorInfo& info) { | 4575 v8::Local<v8::String> property, |
4572 return CompileRun("throw new Error('Error message');"); | 4576 const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 4577 CompileRun("throw new Error('Error message');"); |
4573 } | 4578 } |
4574 | 4579 |
4575 | 4580 |
4576 TEST(NativeGetterThrowingErrorPropertyMirror) { | 4581 TEST(NativeGetterThrowingErrorPropertyMirror) { |
4577 // Create a V8 environment with debug access. | 4582 // Create a V8 environment with debug access. |
4578 DebugLocalContext env; | 4583 DebugLocalContext env; |
4579 v8::HandleScope scope(env->GetIsolate()); | 4584 v8::HandleScope scope(env->GetIsolate()); |
4580 env.ExposeDebug(); | 4585 env.ExposeDebug(); |
4581 | 4586 |
4582 v8::Handle<v8::String> name = v8::String::New("x"); | 4587 v8::Handle<v8::String> name = v8::String::New("x"); |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5105 void Run(); | 5110 void Run(); |
5106 }; | 5111 }; |
5107 | 5112 |
5108 class DebuggerThread : public v8::internal::Thread { | 5113 class DebuggerThread : public v8::internal::Thread { |
5109 public: | 5114 public: |
5110 DebuggerThread() : Thread("DebuggerThread") { } | 5115 DebuggerThread() : Thread("DebuggerThread") { } |
5111 void Run(); | 5116 void Run(); |
5112 }; | 5117 }; |
5113 | 5118 |
5114 | 5119 |
5115 static v8::Handle<v8::Value> ThreadedAtBarrier1(const v8::Arguments& args) { | 5120 static void ThreadedAtBarrier1( |
| 5121 const v8::FunctionCallbackInfo<v8::Value>& args) { |
5116 threaded_debugging_barriers.barrier_1.Wait(); | 5122 threaded_debugging_barriers.barrier_1.Wait(); |
5117 return v8::Undefined(); | |
5118 } | 5123 } |
5119 | 5124 |
5120 | 5125 |
5121 static void ThreadedMessageHandler(const v8::Debug::Message& message) { | 5126 static void ThreadedMessageHandler(const v8::Debug::Message& message) { |
5122 static char print_buffer[1000]; | 5127 static char print_buffer[1000]; |
5123 v8::String::Value json(message.GetJSON()); | 5128 v8::String::Value json(message.GetJSON()); |
5124 Utf16ToAscii(*json, json.length(), print_buffer); | 5129 Utf16ToAscii(*json, json.length(), print_buffer); |
5125 if (IsBreakEventMessage(print_buffer)) { | 5130 if (IsBreakEventMessage(print_buffer)) { |
5126 // Check that we are inside the while loop. | 5131 // Check that we are inside the while loop. |
5127 int source_line = GetSourceLineFromBreakEventMessage(print_buffer); | 5132 int source_line = GetSourceLineFromBreakEventMessage(print_buffer); |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5473 "var x = 3;" | 5478 "var x = 3;" |
5474 "(function (exec_state) {" | 5479 "(function (exec_state) {" |
5475 " if (exec_state.y) return x - 1;" | 5480 " if (exec_state.y) return x - 1;" |
5476 " exec_state.y = x;" | 5481 " exec_state.y = x;" |
5477 " return exec_state.y" | 5482 " return exec_state.y" |
5478 "})"; | 5483 "})"; |
5479 v8::Handle<v8::Function> debugger_call_with_closure; | 5484 v8::Handle<v8::Function> debugger_call_with_closure; |
5480 | 5485 |
5481 // Function to retrieve the number of JavaScript frames by calling a JavaScript | 5486 // Function to retrieve the number of JavaScript frames by calling a JavaScript |
5482 // in the debugger. | 5487 // in the debugger. |
5483 static v8::Handle<v8::Value> CheckFrameCount(const v8::Arguments& args) { | 5488 static void CheckFrameCount(const v8::FunctionCallbackInfo<v8::Value>& args) { |
5484 CHECK(v8::Debug::Call(frame_count)->IsNumber()); | 5489 CHECK(v8::Debug::Call(frame_count)->IsNumber()); |
5485 CHECK_EQ(args[0]->Int32Value(), | 5490 CHECK_EQ(args[0]->Int32Value(), |
5486 v8::Debug::Call(frame_count)->Int32Value()); | 5491 v8::Debug::Call(frame_count)->Int32Value()); |
5487 return v8::Undefined(); | |
5488 } | 5492 } |
5489 | 5493 |
5490 | 5494 |
5491 // Function to retrieve the source line of the top JavaScript frame by calling a | 5495 // Function to retrieve the source line of the top JavaScript frame by calling a |
5492 // JavaScript function in the debugger. | 5496 // JavaScript function in the debugger. |
5493 static v8::Handle<v8::Value> CheckSourceLine(const v8::Arguments& args) { | 5497 static void CheckSourceLine(const v8::FunctionCallbackInfo<v8::Value>& args) { |
5494 CHECK(v8::Debug::Call(frame_source_line)->IsNumber()); | 5498 CHECK(v8::Debug::Call(frame_source_line)->IsNumber()); |
5495 CHECK_EQ(args[0]->Int32Value(), | 5499 CHECK_EQ(args[0]->Int32Value(), |
5496 v8::Debug::Call(frame_source_line)->Int32Value()); | 5500 v8::Debug::Call(frame_source_line)->Int32Value()); |
5497 return v8::Undefined(); | |
5498 } | 5501 } |
5499 | 5502 |
5500 | 5503 |
5501 // Function to test passing an additional parameter to a JavaScript function | 5504 // Function to test passing an additional parameter to a JavaScript function |
5502 // called in the debugger. It also tests that functions called in the debugger | 5505 // called in the debugger. It also tests that functions called in the debugger |
5503 // can throw exceptions. | 5506 // can throw exceptions. |
5504 static v8::Handle<v8::Value> CheckDataParameter(const v8::Arguments& args) { | 5507 static void CheckDataParameter( |
| 5508 const v8::FunctionCallbackInfo<v8::Value>& args) { |
5505 v8::Handle<v8::String> data = v8::String::New("Test"); | 5509 v8::Handle<v8::String> data = v8::String::New("Test"); |
5506 CHECK(v8::Debug::Call(debugger_call_with_data, data)->IsString()); | 5510 CHECK(v8::Debug::Call(debugger_call_with_data, data)->IsString()); |
5507 | 5511 |
5508 CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty()); | 5512 CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty()); |
5509 CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty()); | 5513 CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty()); |
5510 | 5514 |
5511 v8::TryCatch catcher; | 5515 v8::TryCatch catcher; |
5512 v8::Debug::Call(debugger_call_with_data); | 5516 v8::Debug::Call(debugger_call_with_data); |
5513 CHECK(catcher.HasCaught()); | 5517 CHECK(catcher.HasCaught()); |
5514 CHECK(catcher.Exception()->IsString()); | 5518 CHECK(catcher.Exception()->IsString()); |
5515 | |
5516 return v8::Undefined(); | |
5517 } | 5519 } |
5518 | 5520 |
5519 | 5521 |
5520 // Function to test using a JavaScript with closure in the debugger. | 5522 // Function to test using a JavaScript with closure in the debugger. |
5521 static v8::Handle<v8::Value> CheckClosure(const v8::Arguments& args) { | 5523 static void CheckClosure(const v8::FunctionCallbackInfo<v8::Value>& args) { |
5522 CHECK(v8::Debug::Call(debugger_call_with_closure)->IsNumber()); | 5524 CHECK(v8::Debug::Call(debugger_call_with_closure)->IsNumber()); |
5523 CHECK_EQ(3, v8::Debug::Call(debugger_call_with_closure)->Int32Value()); | 5525 CHECK_EQ(3, v8::Debug::Call(debugger_call_with_closure)->Int32Value()); |
5524 return v8::Undefined(); | |
5525 } | 5526 } |
5526 | 5527 |
5527 | 5528 |
5528 // Test functions called through the debugger. | 5529 // Test functions called through the debugger. |
5529 TEST(CallFunctionInDebugger) { | 5530 TEST(CallFunctionInDebugger) { |
5530 // Create and enter a context with the functions CheckFrameCount, | 5531 // Create and enter a context with the functions CheckFrameCount, |
5531 // CheckSourceLine and CheckDataParameter installed. | 5532 // CheckSourceLine and CheckDataParameter installed. |
5532 v8::HandleScope scope(v8::Isolate::GetCurrent()); | 5533 v8::HandleScope scope(v8::Isolate::GetCurrent()); |
5533 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); | 5534 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); |
5534 global_template->Set(v8::String::New("CheckFrameCount"), | 5535 global_template->Set(v8::String::New("CheckFrameCount"), |
(...skipping 1475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7010 CheckDebuggerUnloaded(); | 7011 CheckDebuggerUnloaded(); |
7011 } | 7012 } |
7012 | 7013 |
7013 | 7014 |
7014 v8::Handle<v8::Context> debugee_context; | 7015 v8::Handle<v8::Context> debugee_context; |
7015 v8::Handle<v8::Context> debugger_context; | 7016 v8::Handle<v8::Context> debugger_context; |
7016 | 7017 |
7017 | 7018 |
7018 // Property getter that checks that current and calling contexts | 7019 // Property getter that checks that current and calling contexts |
7019 // are both the debugee contexts. | 7020 // are both the debugee contexts. |
7020 static v8::Handle<v8::Value> NamedGetterWithCallingContextCheck( | 7021 static void NamedGetterWithCallingContextCheck( |
7021 v8::Local<v8::String> name, | 7022 v8::Local<v8::String> name, |
7022 const v8::AccessorInfo& info) { | 7023 const v8::PropertyCallbackInfo<v8::Value>& info) { |
7023 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(name), "a")); | 7024 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(name), "a")); |
7024 v8::Handle<v8::Context> current = v8::Context::GetCurrent(); | 7025 v8::Handle<v8::Context> current = v8::Context::GetCurrent(); |
7025 CHECK(current == debugee_context); | 7026 CHECK(current == debugee_context); |
7026 CHECK(current != debugger_context); | 7027 CHECK(current != debugger_context); |
7027 v8::Handle<v8::Context> calling = v8::Context::GetCalling(); | 7028 v8::Handle<v8::Context> calling = v8::Context::GetCalling(); |
7028 CHECK(calling == debugee_context); | 7029 CHECK(calling == debugee_context); |
7029 CHECK(calling != debugger_context); | 7030 CHECK(calling != debugger_context); |
7030 return v8::Int32::New(1); | 7031 info.GetReturnValue().Set(1); |
7031 } | 7032 } |
7032 | 7033 |
7033 | 7034 |
7034 // Debug event listener that checks if the first argument of a function is | 7035 // Debug event listener that checks if the first argument of a function is |
7035 // an object with property 'a' == 1. If the property has custom accessor | 7036 // an object with property 'a' == 1. If the property has custom accessor |
7036 // this handler will eventually invoke it. | 7037 // this handler will eventually invoke it. |
7037 static void DebugEventGetAtgumentPropertyValue( | 7038 static void DebugEventGetAtgumentPropertyValue( |
7038 v8::DebugEvent event, | 7039 v8::DebugEvent event, |
7039 v8::Handle<v8::Object> exec_state, | 7040 v8::Handle<v8::Object> exec_state, |
7040 v8::Handle<v8::Object> event_data, | 7041 v8::Handle<v8::Object> event_data, |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7295 // TODO(3141533): We should be able to get the real value for | 7296 // TODO(3141533): We should be able to get the real value for |
7296 // optimized frames. | 7297 // optimized frames. |
7297 result = frame_local_value->Call(exec_state, argc, argv); | 7298 result = frame_local_value->Call(exec_state, argc, argv); |
7298 CHECK(result->IsUndefined() || (result->Int32Value() == 42)); | 7299 CHECK(result->IsUndefined() || (result->Int32Value() == 42)); |
7299 } | 7300 } |
7300 } | 7301 } |
7301 } | 7302 } |
7302 } | 7303 } |
7303 | 7304 |
7304 | 7305 |
7305 static v8::Handle<v8::Value> ScheduleBreak(const v8::Arguments& args) { | 7306 static void ScheduleBreak(const v8::FunctionCallbackInfo<v8::Value>& args) { |
7306 v8::Debug::SetDebugEventListener(DebugEventBreakWithOptimizedStack, | 7307 v8::Debug::SetDebugEventListener(DebugEventBreakWithOptimizedStack, |
7307 v8::Undefined()); | 7308 v8::Undefined()); |
7308 v8::Debug::DebugBreak(); | 7309 v8::Debug::DebugBreak(); |
7309 return v8::Undefined(); | |
7310 } | 7310 } |
7311 | 7311 |
7312 | 7312 |
7313 TEST(DebugBreakStackInspection) { | 7313 TEST(DebugBreakStackInspection) { |
7314 DebugLocalContext env; | 7314 DebugLocalContext env; |
7315 v8::HandleScope scope(env->GetIsolate()); | 7315 v8::HandleScope scope(env->GetIsolate()); |
7316 | 7316 |
7317 frame_function_name = | 7317 frame_function_name = |
7318 CompileFunction(&env, frame_function_name_source, "frame_function_name"); | 7318 CompileFunction(&env, frame_function_name_source, "frame_function_name"); |
7319 frame_argument_name = | 7319 frame_argument_name = |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7572 TEST(LiveEditDisabled) { | 7572 TEST(LiveEditDisabled) { |
7573 v8::internal::FLAG_allow_natives_syntax = true; | 7573 v8::internal::FLAG_allow_natives_syntax = true; |
7574 LocalContext env; | 7574 LocalContext env; |
7575 v8::HandleScope scope(env->GetIsolate()); | 7575 v8::HandleScope scope(env->GetIsolate()); |
7576 v8::Debug::SetLiveEditEnabled(false); | 7576 v8::Debug::SetLiveEditEnabled(false); |
7577 CompileRun("%LiveEditCompareStrings('', '')"); | 7577 CompileRun("%LiveEditCompareStrings('', '')"); |
7578 } | 7578 } |
7579 | 7579 |
7580 | 7580 |
7581 #endif // ENABLE_DEBUGGER_SUPPORT | 7581 #endif // ENABLE_DEBUGGER_SUPPORT |
OLD | NEW |