Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: test/cctest/test-debug.cc

Issue 2529883002: [debug] remove JSON debug protocol related tests. (Closed)
Patch Set: fix Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/cctest.status ('k') | test/inspector/runtime/evaluate-empty-stack.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 12 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <stdlib.h> 28 #include <stdlib.h>
29 29
30 #include "src/v8.h" 30 #include "src/v8.h"
31 31
32 #include "src/api.h" 32 #include "src/api.h"
33 #include "src/base/platform/condition-variable.h"
34 #include "src/base/platform/platform.h"
35 #include "src/compilation-cache.h" 33 #include "src/compilation-cache.h"
36 #include "src/debug/debug-interface.h" 34 #include "src/debug/debug-interface.h"
37 #include "src/debug/debug.h" 35 #include "src/debug/debug.h"
38 #include "src/deoptimizer.h" 36 #include "src/deoptimizer.h"
39 #include "src/frames.h" 37 #include "src/frames.h"
40 #include "src/utils.h" 38 #include "src/utils.h"
41 #include "test/cctest/cctest.h" 39 #include "test/cctest/cctest.h"
42 40
43 using ::v8::base::Mutex;
44 using ::v8::base::LockGuard;
45 using ::v8::base::ConditionVariable;
46 using ::v8::base::OS;
47 using ::v8::base::Semaphore;
48 using ::v8::internal::EmbeddedVector; 41 using ::v8::internal::EmbeddedVector;
49 using ::v8::internal::Object; 42 using ::v8::internal::Object;
50 using ::v8::internal::Handle; 43 using ::v8::internal::Handle;
51 using ::v8::internal::Heap; 44 using ::v8::internal::Heap;
52 using ::v8::internal::JSGlobalProxy; 45 using ::v8::internal::JSGlobalProxy;
53 using ::v8::internal::Code; 46 using ::v8::internal::Code;
54 using ::v8::internal::Debug; 47 using ::v8::internal::Debug;
55 using ::v8::internal::CommandMessage;
56 using ::v8::internal::CommandMessageQueue;
57 using ::v8::internal::StackFrame; 48 using ::v8::internal::StackFrame;
58 using ::v8::internal::StepAction; 49 using ::v8::internal::StepAction;
59 using ::v8::internal::StepIn; // From StepAction enum 50 using ::v8::internal::StepIn; // From StepAction enum
60 using ::v8::internal::StepNext; // From StepAction enum 51 using ::v8::internal::StepNext; // From StepAction enum
61 using ::v8::internal::StepOut; // From StepAction enum 52 using ::v8::internal::StepOut; // From StepAction enum
62 using ::v8::internal::Vector; 53 using ::v8::internal::Vector;
63 using ::v8::internal::StrLength; 54 using ::v8::internal::StrLength;
64 55
65 // Size of temp buffer for formatting small strings. 56 // Size of temp buffer for formatting small strings.
66 #define SMALL_STRING_BUFFER_SIZE 80 57 #define SMALL_STRING_BUFFER_SIZE 80
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 } 392 }
402 393
403 394
404 } // namespace internal 395 } // namespace internal
405 } // namespace v8 396 } // namespace v8
406 397
407 398
408 // Check that the debugger has been fully unloaded. 399 // Check that the debugger has been fully unloaded.
409 static void CheckDebuggerUnloaded(v8::Isolate* isolate, 400 static void CheckDebuggerUnloaded(v8::Isolate* isolate,
410 bool check_functions = false) { 401 bool check_functions = false) {
411 // Let debugger to unload itself synchronously
412 v8::Debug::ProcessDebugMessages(isolate);
413
414 v8::internal::CheckDebuggerUnloaded(check_functions); 402 v8::internal::CheckDebuggerUnloaded(check_functions);
415 } 403 }
416 404
417 405
418 // --- D e b u g E v e n t H a n d l e r s 406 // --- D e b u g E v e n t H a n d l e r s
419 // --- 407 // ---
420 // --- The different tests uses a number of debug event handlers. 408 // --- The different tests uses a number of debug event handlers.
421 // --- 409 // ---
422 410
423 411
(...skipping 2061 matching lines...) Expand 10 before | Expand all | Expand 10 after
2485 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked(); 2473 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
2486 CHECK_EQ(1, debugEventCount); 2474 CHECK_EQ(1, debugEventCount);
2487 2475
2488 checkGlobalEvalFunction.Clear(); 2476 checkGlobalEvalFunction.Clear();
2489 checkFrameEvalFunction.Clear(); 2477 checkFrameEvalFunction.Clear();
2490 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); 2478 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2491 CheckDebuggerUnloaded(env->GetIsolate()); 2479 CheckDebuggerUnloaded(env->GetIsolate());
2492 } 2480 }
2493 2481
2494 2482
2495 // Copies a C string to a 16-bit string. Does not check for buffer overflow.
2496 // Does not use the V8 engine to convert strings, so it can be used
2497 // in any thread. Returns the length of the string.
2498 int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
2499 int i;
2500 for (i = 0; input_buffer[i] != '\0'; ++i) {
2501 // ASCII does not use chars > 127, but be careful anyway.
2502 output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
2503 }
2504 output_buffer[i] = 0;
2505 return i;
2506 }
2507
2508
2509 // Copies a 16-bit string to a C string by dropping the high byte of
2510 // each character. Does not check for buffer overflow.
2511 // Can be used in any thread. Requires string length as an input.
2512 int Utf16ToAscii(const uint16_t* input_buffer, int length,
2513 char* output_buffer, int output_len = -1) {
2514 if (output_len >= 0) {
2515 if (length > output_len - 1) {
2516 length = output_len - 1;
2517 }
2518 }
2519
2520 for (int i = 0; i < length; ++i) {
2521 output_buffer[i] = static_cast<char>(input_buffer[i]);
2522 }
2523 output_buffer[length] = '\0';
2524 return length;
2525 }
2526
2527
2528 // We match parts of the message to get evaluate result int value.
2529 bool GetEvaluateStringResult(char *message, char* buffer, int buffer_size) {
2530 if (strstr(message, "\"command\":\"evaluate\"") == NULL) {
2531 return false;
2532 }
2533 const char* prefix = "\"text\":\"";
2534 char* pos1 = strstr(message, prefix);
2535 if (pos1 == NULL) {
2536 return false;
2537 }
2538 pos1 += strlen(prefix);
2539 char* pos2 = strchr(pos1, '"');
2540 if (pos2 == NULL) {
2541 return false;
2542 }
2543 Vector<char> buf(buffer, buffer_size);
2544 int len = static_cast<int>(pos2 - pos1);
2545 if (len > buffer_size - 1) {
2546 len = buffer_size - 1;
2547 }
2548 StrNCpy(buf, pos1, len);
2549 buffer[buffer_size - 1] = '\0';
2550 return true;
2551 }
2552
2553
2554 struct EvaluateResult {
2555 static const int kBufferSize = 20;
2556 char buffer[kBufferSize];
2557 };
2558
2559 struct DebugProcessDebugMessagesData {
2560 static const int kArraySize = 5;
2561 int counter;
2562 EvaluateResult results[kArraySize];
2563
2564 void reset() {
2565 counter = 0;
2566 }
2567 EvaluateResult* current() {
2568 return &results[counter % kArraySize];
2569 }
2570 void next() {
2571 counter++;
2572 }
2573 };
2574
2575 DebugProcessDebugMessagesData process_debug_messages_data;
2576
2577 static void DebugProcessDebugMessagesHandler(
2578 const v8::Debug::Message& message) {
2579 v8::Local<v8::String> json = message.GetJSON();
2580 v8::String::Utf8Value utf8(json);
2581 EvaluateResult* array_item = process_debug_messages_data.current();
2582
2583 bool res = GetEvaluateStringResult(*utf8,
2584 array_item->buffer,
2585 EvaluateResult::kBufferSize);
2586 if (res) {
2587 process_debug_messages_data.next();
2588 }
2589 }
2590
2591
2592 // Test that the evaluation of expressions works even from ProcessDebugMessages
2593 // i.e. with empty stack.
2594 TEST(DebugEvaluateWithoutStack) {
2595 DebugLocalContext env;
2596 v8::Debug::SetMessageHandler(env->GetIsolate(),
2597 DebugProcessDebugMessagesHandler);
2598 v8::HandleScope scope(env->GetIsolate());
2599
2600 const char* source =
2601 "var v1 = 'Pinguin';\n function getAnimal() { return 'Capy' + 'bara'; }";
2602
2603 v8::Local<v8::Context> context = env.context();
2604 v8::Script::Compile(context, v8_str(env->GetIsolate(), source))
2605 .ToLocalChecked()
2606 ->Run(context)
2607 .ToLocalChecked();
2608
2609 v8::Debug::ProcessDebugMessages(env->GetIsolate());
2610
2611 const int kBufferSize = 1000;
2612 uint16_t buffer[kBufferSize];
2613
2614 const char* command_111 = "{\"seq\":111,"
2615 "\"type\":\"request\","
2616 "\"command\":\"evaluate\","
2617 "\"arguments\":{"
2618 " \"global\":true,"
2619 " \"expression\":\"v1\",\"disable_break\":true"
2620 "}}";
2621
2622 v8::Isolate* isolate = CcTest::isolate();
2623 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_111, buffer));
2624
2625 const char* command_112 = "{\"seq\":112,"
2626 "\"type\":\"request\","
2627 "\"command\":\"evaluate\","
2628 "\"arguments\":{"
2629 " \"global\":true,"
2630 " \"expression\":\"getAnimal()\",\"disable_break\":true"
2631 "}}";
2632
2633 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_112, buffer));
2634
2635 const char* command_113 = "{\"seq\":113,"
2636 "\"type\":\"request\","
2637 "\"command\":\"evaluate\","
2638 "\"arguments\":{"
2639 " \"global\":true,"
2640 " \"expression\":\"239 + 566\",\"disable_break\":true"
2641 "}}";
2642
2643 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_113, buffer));
2644
2645 v8::Debug::ProcessDebugMessages(isolate);
2646
2647 CHECK_EQ(3, process_debug_messages_data.counter);
2648
2649 CHECK_EQ(strcmp("Pinguin", process_debug_messages_data.results[0].buffer), 0);
2650 CHECK_EQ(strcmp("Capybara", process_debug_messages_data.results[1].buffer),
2651 0);
2652 CHECK_EQ(strcmp("805", process_debug_messages_data.results[2].buffer), 0);
2653
2654 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
2655 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
2656 CheckDebuggerUnloaded(env->GetIsolate());
2657 }
2658
2659
2660 // Simple test of the stepping mechanism using only store ICs. 2483 // Simple test of the stepping mechanism using only store ICs.
2661 TEST(DebugStepLinear) { 2484 TEST(DebugStepLinear) {
2662 DebugLocalContext env; 2485 DebugLocalContext env;
2663 v8::HandleScope scope(env->GetIsolate()); 2486 v8::HandleScope scope(env->GetIsolate());
2664 2487
2665 // Create a function for testing stepping. 2488 // Create a function for testing stepping.
2666 v8::Local<v8::Function> foo = CompileFunction(&env, 2489 v8::Local<v8::Function> foo = CompileFunction(&env,
2667 "function foo(){a=1;b=1;c=1;}", 2490 "function foo(){a=1;b=1;c=1;}",
2668 "foo"); 2491 "foo");
2669 2492
(...skipping 2265 matching lines...) Expand 10 before | Expand all | Expand 10 after
4935 .FromJust()); 4758 .FromJust());
4936 CHECK(CompileRun("obj_mirror.property('a').value().value() == 1") 4759 CHECK(CompileRun("obj_mirror.property('a').value().value() == 1")
4937 ->BooleanValue(context) 4760 ->BooleanValue(context)
4938 .FromJust()); 4761 .FromJust());
4939 CHECK(CompileRun("obj_mirror.property('b').value().value() == 2") 4762 CHECK(CompileRun("obj_mirror.property('b').value().value() == 2")
4940 ->BooleanValue(context) 4763 ->BooleanValue(context)
4941 .FromJust()); 4764 .FromJust());
4942 } 4765 }
4943 4766
4944 4767
4945 // Multithreaded tests of JSON debugger protocol
4946
4947 // Support classes
4948
4949 // Provides synchronization between N threads, where N is a template parameter.
4950 // The Wait() call blocks a thread until it is called for the Nth time, then all
4951 // calls return. Each ThreadBarrier object can only be used once.
4952 template <int N>
4953 class ThreadBarrier final {
4954 public:
4955 ThreadBarrier() : num_blocked_(0) {}
4956
4957 ~ThreadBarrier() {
4958 LockGuard<Mutex> lock_guard(&mutex_);
4959 if (num_blocked_ != 0) {
4960 CHECK_EQ(N, num_blocked_);
4961 }
4962 }
4963
4964 void Wait() {
4965 LockGuard<Mutex> lock_guard(&mutex_);
4966 CHECK_LT(num_blocked_, N);
4967 num_blocked_++;
4968 if (N == num_blocked_) {
4969 // Signal and unblock all waiting threads.
4970 cv_.NotifyAll();
4971 printf("BARRIER\n\n");
4972 fflush(stdout);
4973 } else { // Wait for the semaphore.
4974 while (num_blocked_ < N) {
4975 cv_.Wait(&mutex_);
4976 }
4977 }
4978 CHECK_EQ(N, num_blocked_);
4979 }
4980
4981 private:
4982 ConditionVariable cv_;
4983 Mutex mutex_;
4984 int num_blocked_;
4985
4986 STATIC_ASSERT(N > 0);
4987
4988 DISALLOW_COPY_AND_ASSIGN(ThreadBarrier);
4989 };
4990
4991
4992 // A set containing enough barriers and semaphores for any of the tests.
4993 class Barriers {
4994 public:
4995 Barriers() : semaphore_1(0), semaphore_2(0) {}
4996 ThreadBarrier<2> barrier_1;
4997 ThreadBarrier<2> barrier_2;
4998 ThreadBarrier<2> barrier_3;
4999 ThreadBarrier<2> barrier_4;
5000 ThreadBarrier<2> barrier_5;
5001 v8::base::Semaphore semaphore_1;
5002 v8::base::Semaphore semaphore_2;
5003 };
5004
5005
5006 // We match parts of the message to decide if it is a break message.
5007 bool IsBreakEventMessage(char *message) {
5008 const char* type_event = "\"type\":\"event\"";
5009 const char* event_break = "\"event\":\"break\"";
5010 // Does the message contain both type:event and event:break?
5011 return strstr(message, type_event) != NULL &&
5012 strstr(message, event_break) != NULL;
5013 }
5014
5015
5016 // We match parts of the message to decide if it is a exception message.
5017 bool IsExceptionEventMessage(char *message) {
5018 const char* type_event = "\"type\":\"event\"";
5019 const char* event_exception = "\"event\":\"exception\"";
5020 // Does the message contain both type:event and event:exception?
5021 return strstr(message, type_event) != NULL &&
5022 strstr(message, event_exception) != NULL;
5023 }
5024
5025
5026 // We match the message wether it is an evaluate response message.
5027 bool IsEvaluateResponseMessage(char* message) {
5028 const char* type_response = "\"type\":\"response\"";
5029 const char* command_evaluate = "\"command\":\"evaluate\"";
5030 // Does the message contain both type:response and command:evaluate?
5031 return strstr(message, type_response) != NULL &&
5032 strstr(message, command_evaluate) != NULL;
5033 }
5034
5035
5036 static int StringToInt(const char* s) {
5037 return atoi(s); // NOLINT
5038 }
5039
5040
5041 // We match parts of the message to get evaluate result int value.
5042 int GetEvaluateIntResult(char *message) {
5043 const char* value = "\"value\":";
5044 char* pos = strstr(message, value);
5045 if (pos == NULL) {
5046 return -1;
5047 }
5048 int res = -1;
5049 res = StringToInt(pos + strlen(value));
5050 return res;
5051 }
5052
5053
5054 // We match parts of the message to get hit breakpoint id.
5055 int GetBreakpointIdFromBreakEventMessage(char *message) {
5056 const char* breakpoints = "\"breakpoints\":[";
5057 char* pos = strstr(message, breakpoints);
5058 if (pos == NULL) {
5059 return -1;
5060 }
5061 int res = -1;
5062 res = StringToInt(pos + strlen(breakpoints));
5063 return res;
5064 }
5065
5066
5067 // We match parts of the message to get total frames number.
5068 int GetTotalFramesInt(char *message) {
5069 const char* prefix = "\"totalFrames\":";
5070 char* pos = strstr(message, prefix);
5071 if (pos == NULL) {
5072 return -1;
5073 }
5074 pos += strlen(prefix);
5075 int res = StringToInt(pos);
5076 return res;
5077 }
5078
5079
5080 // We match parts of the message to get source line.
5081 int GetSourceLineFromBreakEventMessage(char *message) {
5082 const char* source_line = "\"sourceLine\":";
5083 char* pos = strstr(message, source_line);
5084 if (pos == NULL) {
5085 return -1;
5086 }
5087 int res = -1;
5088 res = StringToInt(pos + strlen(source_line));
5089 return res;
5090 }
5091
5092
5093 /* Test MessageQueues */
5094 /* Tests the message queues that hold debugger commands and
5095 * response messages to the debugger. Fills queues and makes
5096 * them grow.
5097 */
5098 Barriers message_queue_barriers;
5099
5100 // This is the debugger thread, that executes no v8 calls except
5101 // placing JSON debugger commands in the queue.
5102 class MessageQueueDebuggerThread : public v8::base::Thread {
5103 public:
5104 MessageQueueDebuggerThread()
5105 : Thread(Options("MessageQueueDebuggerThread")) {}
5106 void Run();
5107 };
5108
5109
5110 static void MessageHandler(const v8::Debug::Message& message) {
5111 v8::Local<v8::String> json = message.GetJSON();
5112 v8::String::Utf8Value utf8(json);
5113 if (IsBreakEventMessage(*utf8)) {
5114 // Lets test script wait until break occurs to send commands.
5115 // Signals when a break is reported.
5116 message_queue_barriers.semaphore_2.Signal();
5117 }
5118
5119 // Allow message handler to block on a semaphore, to test queueing of
5120 // messages while blocked.
5121 message_queue_barriers.semaphore_1.Wait();
5122 }
5123
5124
5125 void MessageQueueDebuggerThread::Run() {
5126 const int kBufferSize = 1000;
5127 uint16_t buffer_1[kBufferSize];
5128 uint16_t buffer_2[kBufferSize];
5129 const char* command_1 =
5130 "{\"seq\":117,"
5131 "\"type\":\"request\","
5132 "\"command\":\"evaluate\","
5133 "\"arguments\":{\"expression\":\"1+2\"}}";
5134 const char* command_2 =
5135 "{\"seq\":118,"
5136 "\"type\":\"request\","
5137 "\"command\":\"evaluate\","
5138 "\"arguments\":{\"expression\":\"1+a\"}}";
5139 const char* command_3 =
5140 "{\"seq\":119,"
5141 "\"type\":\"request\","
5142 "\"command\":\"evaluate\","
5143 "\"arguments\":{\"expression\":\"c.d * b\"}}";
5144 const char* command_continue =
5145 "{\"seq\":106,"
5146 "\"type\":\"request\","
5147 "\"command\":\"continue\"}";
5148 const char* command_single_step =
5149 "{\"seq\":107,"
5150 "\"type\":\"request\","
5151 "\"command\":\"continue\","
5152 "\"arguments\":{\"stepaction\":\"next\"}}";
5153
5154 /* Interleaved sequence of actions by the two threads:*/
5155 // Main thread compiles and runs source_1
5156 message_queue_barriers.semaphore_1.Signal();
5157 message_queue_barriers.barrier_1.Wait();
5158 // Post 6 commands, filling the command queue and making it expand.
5159 // These calls return immediately, but the commands stay on the queue
5160 // until the execution of source_2.
5161 // Note: AsciiToUtf16 executes before SendCommand, so command is copied
5162 // to buffer before buffer is sent to SendCommand.
5163 v8::Isolate* isolate = CcTest::isolate();
5164 v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
5165 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
5166 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
5167 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
5168 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
5169 message_queue_barriers.barrier_2.Wait();
5170 // Main thread compiles and runs source_2.
5171 // Queued commands are executed at the start of compilation of source_2(
5172 // beforeCompile event).
5173 // Free the message handler to process all the messages from the queue. 7
5174 // messages are expected: 2 afterCompile events and 5 responses.
5175 // All the commands added so far will fail to execute as long as call stack
5176 // is empty on beforeCompile event.
5177 for (int i = 0; i < 6 ; ++i) {
5178 message_queue_barriers.semaphore_1.Signal();
5179 }
5180 message_queue_barriers.barrier_3.Wait();
5181 // Main thread compiles and runs source_3.
5182 // Don't stop in the afterCompile handler.
5183 message_queue_barriers.semaphore_1.Signal();
5184 // source_3 includes a debugger statement, which causes a break event.
5185 // Wait on break event from hitting "debugger" statement
5186 message_queue_barriers.semaphore_2.Wait();
5187 // These should execute after the "debugger" statement in source_2
5188 v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
5189 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
5190 v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
5191 v8::Debug::SendCommand(
5192 isolate, buffer_2, AsciiToUtf16(command_single_step, buffer_2));
5193 // Run after 2 break events, 4 responses.
5194 for (int i = 0; i < 6 ; ++i) {
5195 message_queue_barriers.semaphore_1.Signal();
5196 }
5197 // Wait on break event after a single step executes.
5198 message_queue_barriers.semaphore_2.Wait();
5199 v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_2, buffer_1));
5200 v8::Debug::SendCommand(
5201 isolate, buffer_2, AsciiToUtf16(command_continue, buffer_2));
5202 // Run after 2 responses.
5203 for (int i = 0; i < 2 ; ++i) {
5204 message_queue_barriers.semaphore_1.Signal();
5205 }
5206 // Main thread continues running source_3 to end, waits for this thread.
5207 }
5208
5209
5210 // This thread runs the v8 engine.
5211 TEST(MessageQueues) {
5212 MessageQueueDebuggerThread message_queue_debugger_thread;
5213
5214 // Create a V8 environment
5215 DebugLocalContext env;
5216 v8::HandleScope scope(env->GetIsolate());
5217 v8::Debug::SetMessageHandler(env->GetIsolate(), MessageHandler);
5218 message_queue_debugger_thread.Start();
5219
5220 const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
5221 const char* source_2 = "e = 17;";
5222 const char* source_3 = "a = 4; debugger; a = 5; a = 6; a = 7;";
5223
5224 // See MessageQueueDebuggerThread::Run for interleaved sequence of
5225 // API calls and events in the two threads.
5226 CompileRun(source_1);
5227 message_queue_barriers.barrier_1.Wait();
5228 message_queue_barriers.barrier_2.Wait();
5229 CompileRun(source_2);
5230 message_queue_barriers.barrier_3.Wait();
5231 CompileRun(source_3);
5232 message_queue_debugger_thread.Join();
5233 fflush(stdout);
5234 }
5235
5236
5237 class TestClientData : public v8::Debug::ClientData {
5238 public:
5239 TestClientData() {
5240 constructor_call_counter++;
5241 }
5242 virtual ~TestClientData() {
5243 destructor_call_counter++;
5244 }
5245
5246 static void ResetCounters() {
5247 constructor_call_counter = 0;
5248 destructor_call_counter = 0;
5249 }
5250
5251 static int constructor_call_counter;
5252 static int destructor_call_counter;
5253 };
5254
5255 int TestClientData::constructor_call_counter = 0;
5256 int TestClientData::destructor_call_counter = 0;
5257
5258
5259 // Tests that MessageQueue doesn't destroy client data when expands and
5260 // does destroy when it dies.
5261 TEST(MessageQueueExpandAndDestroy) {
5262 TestClientData::ResetCounters();
5263 { // Create a scope for the queue.
5264 CommandMessageQueue queue(1);
5265 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5266 new TestClientData()));
5267 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5268 new TestClientData()));
5269 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5270 new TestClientData()));
5271 CHECK_EQ(0, TestClientData::destructor_call_counter);
5272 queue.Get().Dispose();
5273 CHECK_EQ(1, TestClientData::destructor_call_counter);
5274 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5275 new TestClientData()));
5276 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5277 new TestClientData()));
5278 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5279 new TestClientData()));
5280 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5281 new TestClientData()));
5282 queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5283 new TestClientData()));
5284 CHECK_EQ(1, TestClientData::destructor_call_counter);
5285 queue.Get().Dispose();
5286 CHECK_EQ(2, TestClientData::destructor_call_counter);
5287 }
5288 // All the client data should be destroyed when the queue is destroyed.
5289 CHECK_EQ(TestClientData::destructor_call_counter,
5290 TestClientData::destructor_call_counter);
5291 }
5292
5293
5294 static int handled_client_data_instances_count = 0;
5295 static void MessageHandlerCountingClientData(
5296 const v8::Debug::Message& message) {
5297 if (message.GetClientData() != NULL) {
5298 handled_client_data_instances_count++;
5299 }
5300 }
5301
5302
5303 // Tests that all client data passed to the debugger are sent to the handler.
5304 TEST(SendClientDataToHandler) {
5305 // Create a V8 environment
5306 DebugLocalContext env;
5307 v8::Isolate* isolate = env->GetIsolate();
5308 v8::HandleScope scope(isolate);
5309 TestClientData::ResetCounters();
5310 handled_client_data_instances_count = 0;
5311 v8::Debug::SetMessageHandler(isolate, MessageHandlerCountingClientData);
5312 const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
5313 const int kBufferSize = 1000;
5314 uint16_t buffer[kBufferSize];
5315 const char* command_1 =
5316 "{\"seq\":117,"
5317 "\"type\":\"request\","
5318 "\"command\":\"evaluate\","
5319 "\"arguments\":{\"expression\":\"1+2\"}}";
5320 const char* command_2 =
5321 "{\"seq\":118,"
5322 "\"type\":\"request\","
5323 "\"command\":\"evaluate\","
5324 "\"arguments\":{\"expression\":\"1+a\"}}";
5325 const char* command_continue =
5326 "{\"seq\":106,"
5327 "\"type\":\"request\","
5328 "\"command\":\"continue\"}";
5329
5330 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer),
5331 new TestClientData());
5332 v8::Debug::SendCommand(
5333 isolate, buffer, AsciiToUtf16(command_2, buffer), NULL);
5334 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
5335 new TestClientData());
5336 v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
5337 new TestClientData());
5338 // All the messages will be processed on beforeCompile event.
5339 CompileRun(source_1);
5340 v8::Debug::SendCommand(
5341 isolate, buffer, AsciiToUtf16(command_continue, buffer));
5342 CHECK_EQ(3, TestClientData::constructor_call_counter);
5343 CHECK_EQ(TestClientData::constructor_call_counter,
5344 handled_client_data_instances_count);
5345 CHECK_EQ(TestClientData::constructor_call_counter,
5346 TestClientData::destructor_call_counter);
5347 }
5348
5349
5350 /* Test ThreadedDebugging */
5351 /* This test interrupts a running infinite loop that is
5352 * occupying the v8 thread by a break command from the
5353 * debugger thread. It then changes the value of a
5354 * global object, to make the loop terminate.
5355 */
5356
5357 Barriers threaded_debugging_barriers;
5358
5359 class V8Thread : public v8::base::Thread {
5360 public:
5361 V8Thread() : Thread(Options("V8Thread")) {}
5362 void Run();
5363 v8::Isolate* isolate() { return isolate_; }
5364
5365 private:
5366 v8::Isolate* isolate_;
5367 };
5368
5369 class DebuggerThread : public v8::base::Thread {
5370 public:
5371 explicit DebuggerThread(v8::Isolate* isolate)
5372 : Thread(Options("DebuggerThread")), isolate_(isolate) {}
5373 void Run();
5374
5375 private:
5376 v8::Isolate* isolate_;
5377 };
5378
5379
5380 static void ThreadedAtBarrier1(
5381 const v8::FunctionCallbackInfo<v8::Value>& args) {
5382 threaded_debugging_barriers.barrier_1.Wait();
5383 }
5384
5385
5386 static void ThreadedMessageHandler(const v8::Debug::Message& message) {
5387 static char print_buffer[1000];
5388 v8::String::Value json(message.GetJSON());
5389 Utf16ToAscii(*json, json.length(), print_buffer);
5390 if (IsBreakEventMessage(print_buffer)) {
5391 // Check that we are inside the while loop.
5392 int source_line = GetSourceLineFromBreakEventMessage(print_buffer);
5393 CHECK(4 <= source_line && source_line <= 10);
5394 threaded_debugging_barriers.barrier_2.Wait();
5395 }
5396 }
5397
5398
5399 void V8Thread::Run() {
5400 const char* source =
5401 "flag = true;\n"
5402 "\n"
5403 "function foo() {\n"
5404 " var x = 1;\n"
5405 " while ( flag == true ) {\n"
5406 " if ( x == 1 ) {\n"
5407 " ThreadedAtBarrier1();\n"
5408 " }\n"
5409 " x = x + 1;\n"
5410 " }\n"
5411 "}\n"
5412 "\n"
5413 "foo();\n";
5414
5415 v8::Isolate::CreateParams create_params;
5416 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
5417 isolate_ = v8::Isolate::New(create_params);
5418 threaded_debugging_barriers.barrier_3.Wait();
5419 {
5420 v8::Isolate::Scope isolate_scope(isolate_);
5421 DebugLocalContext env(isolate_);
5422 v8::HandleScope scope(isolate_);
5423 v8::Debug::SetMessageHandler(isolate_, &ThreadedMessageHandler);
5424 v8::Local<v8::ObjectTemplate> global_template =
5425 v8::ObjectTemplate::New(env->GetIsolate());
5426 global_template->Set(
5427 v8_str(env->GetIsolate(), "ThreadedAtBarrier1"),
5428 v8::FunctionTemplate::New(isolate_, ThreadedAtBarrier1));
5429 v8::Local<v8::Context> context =
5430 v8::Context::New(isolate_, NULL, global_template);
5431 v8::Context::Scope context_scope(context);
5432
5433 CompileRun(source);
5434 }
5435 threaded_debugging_barriers.barrier_4.Wait();
5436 isolate_->Dispose();
5437 }
5438
5439
5440 void DebuggerThread::Run() {
5441 const int kBufSize = 1000;
5442 uint16_t buffer[kBufSize];
5443
5444 const char* command_1 =
5445 "{\"seq\":102,"
5446 "\"type\":\"request\","
5447 "\"command\":\"evaluate\","
5448 "\"arguments\":{\"expression\":\"flag = false\"}}";
5449 const char* command_2 = "{\"seq\":103,"
5450 "\"type\":\"request\","
5451 "\"command\":\"continue\"}";
5452
5453 threaded_debugging_barriers.barrier_1.Wait();
5454 v8::Debug::DebugBreak(isolate_);
5455 threaded_debugging_barriers.barrier_2.Wait();
5456 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer));
5457 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer));
5458 threaded_debugging_barriers.barrier_4.Wait();
5459 }
5460
5461
5462 TEST(ThreadedDebugging) {
5463 V8Thread v8_thread;
5464
5465 // Create a V8 environment
5466 v8_thread.Start();
5467 threaded_debugging_barriers.barrier_3.Wait();
5468 DebuggerThread debugger_thread(v8_thread.isolate());
5469 debugger_thread.Start();
5470
5471 v8_thread.Join();
5472 debugger_thread.Join();
5473 }
5474
5475
5476 /* Test RecursiveBreakpoints */
5477 /* In this test, the debugger evaluates a function with a breakpoint, after
5478 * hitting a breakpoint in another function. We do this with both values
5479 * of the flag enabling recursive breakpoints, and verify that the second
5480 * breakpoint is hit when enabled, and missed when disabled.
5481 */
5482
5483 class BreakpointsV8Thread : public v8::base::Thread {
5484 public:
5485 BreakpointsV8Thread() : Thread(Options("BreakpointsV8Thread")) {}
5486 void Run();
5487
5488 v8::Isolate* isolate() { return isolate_; }
5489
5490 private:
5491 v8::Isolate* isolate_;
5492 };
5493
5494 class BreakpointsDebuggerThread : public v8::base::Thread {
5495 public:
5496 BreakpointsDebuggerThread(bool global_evaluate, v8::Isolate* isolate)
5497 : Thread(Options("BreakpointsDebuggerThread")),
5498 global_evaluate_(global_evaluate),
5499 isolate_(isolate) {}
5500 void Run();
5501
5502 private:
5503 bool global_evaluate_;
5504 v8::Isolate* isolate_;
5505 };
5506
5507
5508 Barriers* breakpoints_barriers;
5509 int break_event_breakpoint_id;
5510 int evaluate_int_result;
5511
5512 static void BreakpointsMessageHandler(const v8::Debug::Message& message) {
5513 static char print_buffer[1000];
5514 v8::String::Value json(message.GetJSON());
5515 Utf16ToAscii(*json, json.length(), print_buffer);
5516
5517 if (IsBreakEventMessage(print_buffer)) {
5518 break_event_breakpoint_id =
5519 GetBreakpointIdFromBreakEventMessage(print_buffer);
5520 breakpoints_barriers->semaphore_1.Signal();
5521 } else if (IsEvaluateResponseMessage(print_buffer)) {
5522 evaluate_int_result = GetEvaluateIntResult(print_buffer);
5523 breakpoints_barriers->semaphore_1.Signal();
5524 }
5525 }
5526
5527
5528 void BreakpointsV8Thread::Run() {
5529 const char* source_1 = "var y_global = 3;\n"
5530 "function cat( new_value ) {\n"
5531 " var x = new_value;\n"
5532 " y_global = y_global + 4;\n"
5533 " x = 3 * x + 1;\n"
5534 " y_global = y_global + 5;\n"
5535 " return x;\n"
5536 "}\n"
5537 "\n"
5538 "function dog() {\n"
5539 " var x = 1;\n"
5540 " x = y_global;"
5541 " var z = 3;"
5542 " x += 100;\n"
5543 " return x;\n"
5544 "}\n"
5545 "\n";
5546 const char* source_2 = "cat(17);\n"
5547 "cat(19);\n";
5548
5549 v8::Isolate::CreateParams create_params;
5550 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
5551 isolate_ = v8::Isolate::New(create_params);
5552 breakpoints_barriers->barrier_3.Wait();
5553 {
5554 v8::Isolate::Scope isolate_scope(isolate_);
5555 DebugLocalContext env(isolate_);
5556 v8::HandleScope scope(isolate_);
5557 v8::Debug::SetMessageHandler(isolate_, &BreakpointsMessageHandler);
5558
5559 CompileRun(source_1);
5560 breakpoints_barriers->barrier_1.Wait();
5561 breakpoints_barriers->barrier_2.Wait();
5562 CompileRun(source_2);
5563 }
5564 breakpoints_barriers->barrier_4.Wait();
5565 isolate_->Dispose();
5566 }
5567
5568
5569 void BreakpointsDebuggerThread::Run() {
5570 const int kBufSize = 1000;
5571 uint16_t buffer[kBufSize];
5572
5573 const char* command_1 = "{\"seq\":101,"
5574 "\"type\":\"request\","
5575 "\"command\":\"setbreakpoint\","
5576 "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
5577 const char* command_2 = "{\"seq\":102,"
5578 "\"type\":\"request\","
5579 "\"command\":\"setbreakpoint\","
5580 "\"arguments\":{\"type\":\"function\",\"target\":\"dog\",\"line\":3}}";
5581 const char* command_3;
5582 if (this->global_evaluate_) {
5583 command_3 = "{\"seq\":103,"
5584 "\"type\":\"request\","
5585 "\"command\":\"evaluate\","
5586 "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false,"
5587 "\"global\":true}}";
5588 } else {
5589 command_3 = "{\"seq\":103,"
5590 "\"type\":\"request\","
5591 "\"command\":\"evaluate\","
5592 "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false}}";
5593 }
5594 const char* command_4;
5595 if (this->global_evaluate_) {
5596 command_4 = "{\"seq\":104,"
5597 "\"type\":\"request\","
5598 "\"command\":\"evaluate\","
5599 "\"arguments\":{\"expression\":\"100 + 8\",\"disable_break\":true,"
5600 "\"global\":true}}";
5601 } else {
5602 command_4 = "{\"seq\":104,"
5603 "\"type\":\"request\","
5604 "\"command\":\"evaluate\","
5605 "\"arguments\":{\"expression\":\"x + 1\",\"disable_break\":true}}";
5606 }
5607 const char* command_5 = "{\"seq\":105,"
5608 "\"type\":\"request\","
5609 "\"command\":\"continue\"}";
5610 const char* command_6 = "{\"seq\":106,"
5611 "\"type\":\"request\","
5612 "\"command\":\"continue\"}";
5613 const char* command_7;
5614 if (this->global_evaluate_) {
5615 command_7 = "{\"seq\":107,"
5616 "\"type\":\"request\","
5617 "\"command\":\"evaluate\","
5618 "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true,"
5619 "\"global\":true}}";
5620 } else {
5621 command_7 = "{\"seq\":107,"
5622 "\"type\":\"request\","
5623 "\"command\":\"evaluate\","
5624 "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true}}";
5625 }
5626 const char* command_8 = "{\"seq\":108,"
5627 "\"type\":\"request\","
5628 "\"command\":\"continue\"}";
5629
5630
5631 // v8 thread initializes, runs source_1
5632 breakpoints_barriers->barrier_1.Wait();
5633 // 1:Set breakpoint in cat() (will get id 1).
5634 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer));
5635 // 2:Set breakpoint in dog() (will get id 2).
5636 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer));
5637 breakpoints_barriers->barrier_2.Wait();
5638 // V8 thread starts compiling source_2.
5639 // Automatic break happens, to run queued commands
5640 // breakpoints_barriers->semaphore_1.Wait();
5641 // Commands 1 through 3 run, thread continues.
5642 // v8 thread runs source_2 to breakpoint in cat().
5643 // message callback receives break event.
5644 breakpoints_barriers->semaphore_1.Wait();
5645 // Must have hit breakpoint #1.
5646 CHECK_EQ(1, break_event_breakpoint_id);
5647 // 4:Evaluate dog() (which has a breakpoint).
5648 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_3, buffer));
5649 // V8 thread hits breakpoint in dog().
5650 breakpoints_barriers->semaphore_1.Wait(); // wait for break event
5651 // Must have hit breakpoint #2.
5652 CHECK_EQ(2, break_event_breakpoint_id);
5653 // 5:Evaluate (x + 1).
5654 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_4, buffer));
5655 // Evaluate (x + 1) finishes.
5656 breakpoints_barriers->semaphore_1.Wait();
5657 // Must have result 108.
5658 CHECK_EQ(108, evaluate_int_result);
5659 // 6:Continue evaluation of dog().
5660 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_5, buffer));
5661 // Evaluate dog() finishes.
5662 breakpoints_barriers->semaphore_1.Wait();
5663 // Must have result 107.
5664 CHECK_EQ(107, evaluate_int_result);
5665 // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint
5666 // in cat(19).
5667 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_6, buffer));
5668 // Message callback gets break event.
5669 breakpoints_barriers->semaphore_1.Wait(); // wait for break event
5670 // Must have hit breakpoint #1.
5671 CHECK_EQ(1, break_event_breakpoint_id);
5672 // 8: Evaluate dog() with breaks disabled.
5673 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_7, buffer));
5674 // Evaluate dog() finishes.
5675 breakpoints_barriers->semaphore_1.Wait();
5676 // Must have result 116.
5677 CHECK_EQ(116, evaluate_int_result);
5678 // 9: Continue evaluation of source2, reach end.
5679 v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_8, buffer));
5680 breakpoints_barriers->barrier_4.Wait();
5681 }
5682
5683
5684 void TestRecursiveBreakpointsGeneric(bool global_evaluate) {
5685 BreakpointsV8Thread breakpoints_v8_thread;
5686
5687 // Create a V8 environment
5688 Barriers stack_allocated_breakpoints_barriers;
5689 breakpoints_barriers = &stack_allocated_breakpoints_barriers;
5690
5691 breakpoints_v8_thread.Start();
5692 breakpoints_barriers->barrier_3.Wait();
5693 BreakpointsDebuggerThread breakpoints_debugger_thread(
5694 global_evaluate, breakpoints_v8_thread.isolate());
5695 breakpoints_debugger_thread.Start();
5696
5697 breakpoints_v8_thread.Join();
5698 breakpoints_debugger_thread.Join();
5699 }
5700
5701
5702 TEST(RecursiveBreakpoints) {
5703 TestRecursiveBreakpointsGeneric(false);
5704 }
5705
5706
5707 TEST(RecursiveBreakpointsGlobal) {
5708 TestRecursiveBreakpointsGeneric(true);
5709 }
5710
5711
5712 TEST(SetDebugEventListenerOnUninitializedVM) { 4768 TEST(SetDebugEventListenerOnUninitializedVM) {
5713 v8::Debug::SetDebugEventListener(CcTest::isolate(), DummyDebugEventListener); 4769 v8::Debug::SetDebugEventListener(CcTest::isolate(), DummyDebugEventListener);
5714 } 4770 }
5715 4771
5716
5717 static void DummyMessageHandler(const v8::Debug::Message& message) {
5718 }
5719
5720
5721 TEST(SetMessageHandlerOnUninitializedVM) {
5722 v8::Debug::SetMessageHandler(CcTest::isolate(), DummyMessageHandler);
5723 }
5724
5725
5726 // Source for a JavaScript function which returns the data parameter of a 4772 // Source for a JavaScript function which returns the data parameter of a
5727 // function called in the context of the debugger. If no data parameter is 4773 // function called in the context of the debugger. If no data parameter is
5728 // passed it throws an exception. 4774 // passed it throws an exception.
5729 static const char* debugger_call_with_data_source = 4775 static const char* debugger_call_with_data_source =
5730 "function debugger_call_with_data(exec_state, data) {" 4776 "function debugger_call_with_data(exec_state, data) {"
5731 " if (data) return data;" 4777 " if (data) return data;"
5732 " throw 'No data!'" 4778 " throw 'No data!'"
5733 "}"; 4779 "}";
5734 v8::Local<v8::Function> debugger_call_with_data; 4780 v8::Local<v8::Function> debugger_call_with_data;
5735 4781
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
5924 " CheckSourceLine(9)\n" 4970 " CheckSourceLine(9)\n"
5925 " CheckSourceLine(10)\n" 4971 " CheckSourceLine(10)\n"
5926 "}; f()"), 4972 "}; f()"),
5927 &origin) 4973 &origin)
5928 .ToLocalChecked() 4974 .ToLocalChecked()
5929 ->Run(context) 4975 ->Run(context)
5930 .ToLocalChecked(); 4976 .ToLocalChecked();
5931 } 4977 }
5932 4978
5933 4979
5934 // Debugger message handler which counts the number of breaks.
5935 static void SendContinueCommand();
5936 static void MessageHandlerBreakPointHitCount(
5937 const v8::Debug::Message& message) {
5938 if (message.IsEvent() && message.GetEvent() == v8::Break) {
5939 // Count the number of breaks.
5940 break_point_hit_count++;
5941
5942 SendContinueCommand();
5943 }
5944 }
5945
5946
5947 // Test that clearing the debug event listener actually clears all break points 4980 // Test that clearing the debug event listener actually clears all break points
5948 // and related information. 4981 // and related information.
5949 TEST(DebuggerUnload) { 4982 TEST(DebuggerUnload) {
5950 DebugLocalContext env; 4983 DebugLocalContext env;
5951 4984
5952 // Check debugger is unloaded before it is used. 4985 // Check debugger is unloaded before it is used.
5953 CheckDebuggerUnloaded(env->GetIsolate()); 4986 CheckDebuggerUnloaded(env->GetIsolate());
5954 4987
5955 // Set a debug event listener. 4988 // Set a debug event listener.
5956 break_point_hit_count = 0; 4989 break_point_hit_count = 0;
(...skipping 19 matching lines...) Expand all
5976 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked(); 5009 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
5977 CHECK_EQ(2, break_point_hit_count); 5010 CHECK_EQ(2, break_point_hit_count);
5978 bar->Call(context, env->Global(), 0, NULL).ToLocalChecked(); 5011 bar->Call(context, env->Global(), 0, NULL).ToLocalChecked();
5979 CHECK_EQ(4, break_point_hit_count); 5012 CHECK_EQ(4, break_point_hit_count);
5980 } 5013 }
5981 5014
5982 // Remove the debug event listener without clearing breakpoints. Do this 5015 // Remove the debug event listener without clearing breakpoints. Do this
5983 // outside a handle scope. 5016 // outside a handle scope.
5984 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); 5017 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
5985 CheckDebuggerUnloaded(env->GetIsolate(), true); 5018 CheckDebuggerUnloaded(env->GetIsolate(), true);
5019 }
5986 5020
5987 // Now set a debug message handler. 5021 int event_listener_hit_count = 0;
5988 break_point_hit_count = 0;
5989 v8::Debug::SetMessageHandler(env->GetIsolate(),
5990 MessageHandlerBreakPointHitCount);
5991 {
5992 v8::HandleScope scope(env->GetIsolate());
5993 5022
5994 // Get the test functions again. 5023 // Debugger event listener which clears itself while active.
5995 v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast( 5024 static void EventListenerClearingItself(
5996 env->Global() 5025 const v8::Debug::EventDetails& details) {
5997 ->Get(context, v8_str(env->GetIsolate(), "foo")) 5026 event_listener_hit_count++;
5998 .ToLocalChecked()));
5999 5027
6000 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked(); 5028 // Clear debug event listener.
6001 CHECK_EQ(0, break_point_hit_count); 5029 v8::Debug::SetDebugEventListener(details.GetIsolate(), nullptr);
6002
6003 // Set break points and run again.
6004 SetBreakPoint(foo, 0);
6005 SetBreakPoint(foo, 4);
6006 foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
6007 CHECK_EQ(2, break_point_hit_count);
6008 }
6009
6010 // Remove the debug message handler without clearing breakpoints. Do this
6011 // outside a handle scope.
6012 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
6013 CheckDebuggerUnloaded(env->GetIsolate(), true);
6014 } 5030 }
6015 5031
6016 5032
6017 // Sends continue command to the debugger. 5033 // Test clearing the debug message handler while processing a debug event.
6018 static void SendContinueCommand() { 5034 TEST(DebuggerClearEventListenerWhileActive) {
6019 const int kBufferSize = 1000;
6020 uint16_t buffer[kBufferSize];
6021 const char* command_continue =
6022 "{\"seq\":0,"
6023 "\"type\":\"request\","
6024 "\"command\":\"continue\"}";
6025
6026 v8::Debug::SendCommand(
6027 CcTest::isolate(), buffer, AsciiToUtf16(command_continue, buffer));
6028 }
6029
6030
6031 // Debugger message handler which counts the number of times it is called.
6032 static int message_handler_hit_count = 0;
6033 static void MessageHandlerHitCount(const v8::Debug::Message& message) {
6034 message_handler_hit_count++;
6035
6036 static char print_buffer[1000];
6037 v8::String::Value json(message.GetJSON());
6038 Utf16ToAscii(*json, json.length(), print_buffer);
6039 if (IsExceptionEventMessage(print_buffer)) {
6040 // Send a continue command for exception events.
6041 SendContinueCommand();
6042 }
6043 }
6044
6045
6046 // Test clearing the debug message handler.
6047 TEST(DebuggerClearMessageHandler) {
6048 DebugLocalContext env; 5035 DebugLocalContext env;
6049 v8::HandleScope scope(env->GetIsolate()); 5036 v8::HandleScope scope(env->GetIsolate());
6050 5037
6051 // Check debugger is unloaded before it is used. 5038 // Check debugger is unloaded before it is used.
6052 CheckDebuggerUnloaded(env->GetIsolate()); 5039 CheckDebuggerUnloaded(env->GetIsolate());
6053 5040
6054 // Set a debug message handler. 5041 // Set a debug event listener.
6055 v8::Debug::SetMessageHandler(env->GetIsolate(), MessageHandlerHitCount); 5042 v8::Debug::SetDebugEventListener(env->GetIsolate(),
5043 EventListenerClearingItself);
6056 5044
6057 // Run code to throw a unhandled exception. This should end up in the message 5045 // Run code to throw an uncaught exception. This should trigger the listener.
6058 // handler.
6059 CompileRun("throw 1"); 5046 CompileRun("throw 1");
6060 5047
6061 // The message handler should be called. 5048 // The event listener should have been called.
6062 CHECK_GT(message_handler_hit_count, 0); 5049 CHECK_EQ(1, event_listener_hit_count);
6063
6064 // Clear debug message handler.
6065 message_handler_hit_count = 0;
6066 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr);
6067
6068 // Run code to throw a unhandled exception. This should end up in the message
6069 // handler.
6070 CompileRun("throw 1");
6071
6072 // The message handler should not be called more.
6073 CHECK_EQ(0, message_handler_hit_count);
6074 5050
6075 CheckDebuggerUnloaded(env->GetIsolate(), true); 5051 CheckDebuggerUnloaded(env->GetIsolate(), true);
6076 } 5052 }
6077 5053
6078
6079 // Debugger message handler which clears the message handler while active.
6080 static void MessageHandlerClearingMessageHandler(
6081 const v8::Debug::Message& message) {
6082 message_handler_hit_count++;
6083
6084 // Clear debug message handler.
6085 v8::Debug::SetMessageHandler(message.GetIsolate(), nullptr);
6086 }
6087
6088
6089 // Test clearing the debug message handler while processing a debug event.
6090 TEST(DebuggerClearMessageHandlerWhileActive) {
6091 DebugLocalContext env;
6092 v8::HandleScope scope(env->GetIsolate());
6093
6094 // Check debugger is unloaded before it is used.
6095 CheckDebuggerUnloaded(env->GetIsolate());
6096
6097 // Set a debug message handler.
6098 v8::Debug::SetMessageHandler(env->GetIsolate(),
6099 MessageHandlerClearingMessageHandler);
6100
6101 // Run code to throw a unhandled exception. This should end up in the message
6102 // handler.
6103 CompileRun("throw 1");
6104
6105 // The message handler should be called.
6106 CHECK_EQ(1, message_handler_hit_count);
6107
6108 CheckDebuggerUnloaded(env->GetIsolate(), true);
6109 }
6110
6111
6112 // Test for issue http://code.google.com/p/v8/issues/detail?id=289. 5054 // Test for issue http://code.google.com/p/v8/issues/detail?id=289.
6113 // Make sure that DebugGetLoadedScripts doesn't return scripts 5055 // Make sure that DebugGetLoadedScripts doesn't return scripts
6114 // with disposed external source. 5056 // with disposed external source.
6115 class EmptyExternalStringResource : public v8::String::ExternalStringResource { 5057 class EmptyExternalStringResource : public v8::String::ExternalStringResource {
6116 public: 5058 public:
6117 EmptyExternalStringResource() { empty_[0] = 0; } 5059 EmptyExternalStringResource() { empty_[0] = 0; }
6118 virtual ~EmptyExternalStringResource() {} 5060 virtual ~EmptyExternalStringResource() {}
6119 virtual size_t length() const { return empty_.length(); } 5061 virtual size_t length() const { return empty_.length(); }
6120 virtual const uint16_t* data() const { return empty_.start(); } 5062 virtual const uint16_t* data() const { return empty_.start(); }
6121 private: 5063 private:
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
6251 f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); 5193 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
6252 CHECK_EQ(4, break_point_hit_count); 5194 CHECK_EQ(4, break_point_hit_count);
6253 } 5195 }
6254 5196
6255 5197
6256 static v8::Local<v8::Context> expected_context; 5198 static v8::Local<v8::Context> expected_context;
6257 static v8::Local<v8::Value> expected_context_data; 5199 static v8::Local<v8::Value> expected_context_data;
6258 5200
6259 5201
6260 // Check that the expected context is the one generating the debug event. 5202 // Check that the expected context is the one generating the debug event.
6261 static void ContextCheckMessageHandler(const v8::Debug::Message& message) { 5203 static void ContextCheckEventListener(
6262 CHECK(message.GetEventContext() == expected_context); 5204 const v8::Debug::EventDetails& event_details) {
6263 CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals( 5205 CHECK(event_details.GetEventContext() == expected_context);
5206 CHECK(event_details.GetEventContext()->GetEmbedderData(0)->StrictEquals(
6264 expected_context_data)); 5207 expected_context_data));
6265 message_handler_hit_count++; 5208 event_listener_hit_count++;
6266
6267 static char print_buffer[1000];
6268 v8::String::Value json(message.GetJSON());
6269 Utf16ToAscii(*json, json.length(), print_buffer);
6270
6271 // Send a continue command for break events.
6272 if (IsBreakEventMessage(print_buffer)) {
6273 SendContinueCommand();
6274 }
6275 } 5209 }
6276 5210
6277 5211
6278 // Test which creates two contexts and sets different embedder data on each. 5212 // Test which creates two contexts and sets different embedder data on each.
6279 // Checks that this data is set correctly and that when the debug message 5213 // Checks that this data is set correctly and that when the debug event
6280 // handler is called the expected context is the one active. 5214 // listener is called the expected context is the one active.
6281 TEST(ContextData) { 5215 TEST(ContextData) {
6282 v8::Isolate* isolate = CcTest::isolate(); 5216 v8::Isolate* isolate = CcTest::isolate();
6283 v8::HandleScope scope(isolate); 5217 v8::HandleScope scope(isolate);
6284 5218
6285 // Create two contexts. 5219 // Create two contexts.
6286 v8::Local<v8::Context> context_1; 5220 v8::Local<v8::Context> context_1;
6287 v8::Local<v8::Context> context_2; 5221 v8::Local<v8::Context> context_2;
6288 v8::Local<v8::ObjectTemplate> global_template = 5222 v8::Local<v8::ObjectTemplate> global_template =
6289 v8::Local<v8::ObjectTemplate>(); 5223 v8::Local<v8::ObjectTemplate>();
6290 v8::Local<v8::Value> global_object = v8::Local<v8::Value>(); 5224 v8::Local<v8::Value> global_object = v8::Local<v8::Value>();
6291 context_1 = v8::Context::New(isolate, NULL, global_template, global_object); 5225 context_1 = v8::Context::New(isolate, NULL, global_template, global_object);
6292 context_2 = v8::Context::New(isolate, NULL, global_template, global_object); 5226 context_2 = v8::Context::New(isolate, NULL, global_template, global_object);
6293 5227
6294 v8::Debug::SetMessageHandler(isolate, ContextCheckMessageHandler); 5228 v8::Debug::SetDebugEventListener(isolate, ContextCheckEventListener);
6295 5229
6296 // Default data value is undefined. 5230 // Default data value is undefined.
6297 CHECK(context_1->GetEmbedderData(0)->IsUndefined()); 5231 CHECK(context_1->GetEmbedderData(0)->IsUndefined());
6298 CHECK(context_2->GetEmbedderData(0)->IsUndefined()); 5232 CHECK(context_2->GetEmbedderData(0)->IsUndefined());
6299 5233
6300 // Set and check different data values. 5234 // Set and check different data values.
6301 v8::Local<v8::String> data_1 = v8_str(isolate, "1"); 5235 v8::Local<v8::String> data_1 = v8_str(isolate, "1");
6302 v8::Local<v8::String> data_2 = v8_str(isolate, "2"); 5236 v8::Local<v8::String> data_2 = v8_str(isolate, "2");
6303 context_1->SetEmbedderData(0, data_1); 5237 context_1->SetEmbedderData(0, data_1);
6304 context_2->SetEmbedderData(0, data_2); 5238 context_2->SetEmbedderData(0, data_2);
(...skipping 16 matching lines...) Expand all
6321 // Enter and run function in the second context. 5255 // Enter and run function in the second context.
6322 { 5256 {
6323 v8::Context::Scope context_scope(context_2); 5257 v8::Context::Scope context_scope(context_2);
6324 expected_context = context_2; 5258 expected_context = context_2;
6325 expected_context_data = data_2; 5259 expected_context_data = data_2;
6326 v8::Local<v8::Function> f = CompileFunction(isolate, source, "f"); 5260 v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
6327 f->Call(context_2, context_2->Global(), 0, NULL).ToLocalChecked(); 5261 f->Call(context_2, context_2->Global(), 0, NULL).ToLocalChecked();
6328 } 5262 }
6329 5263
6330 // Two times compile event and two times break event. 5264 // Two times compile event and two times break event.
6331 CHECK_GT(message_handler_hit_count, 4); 5265 CHECK_GT(event_listener_hit_count, 4);
6332 5266
6333 v8::Debug::SetMessageHandler(isolate, nullptr); 5267 v8::Debug::SetDebugEventListener(isolate, nullptr);
6334 CheckDebuggerUnloaded(isolate); 5268 CheckDebuggerUnloaded(isolate);
6335 } 5269 }
6336 5270
6337 5271 // Debug event listener which issues a debug break when it hits a break event.
6338 // Debug message handler which issues a debug break when it hits a break event. 5272 static int event_listener_break_hit_count = 0;
6339 static int message_handler_break_hit_count = 0; 5273 static void DebugBreakEventListener(const v8::Debug::EventDetails& details) {
6340 static void DebugBreakMessageHandler(const v8::Debug::Message& message) {
6341 // Schedule a debug break for break events. 5274 // Schedule a debug break for break events.
6342 if (message.IsEvent() && message.GetEvent() == v8::Break) { 5275 if (details.GetEvent() == v8::Break) {
6343 message_handler_break_hit_count++; 5276 event_listener_break_hit_count++;
6344 if (message_handler_break_hit_count == 1) { 5277 if (event_listener_break_hit_count == 1) {
6345 v8::Debug::DebugBreak(message.GetIsolate()); 5278 v8::Debug::DebugBreak(details.GetIsolate());
6346 } 5279 }
6347 } 5280 }
6348
6349 // Issue a continue command if this event will not cause the VM to start
6350 // running.
6351 if (!message.WillStartRunning()) {
6352 SendContinueCommand();
6353 }
6354 } 5281 }
6355 5282
6356 5283 // Test that a debug break can be scheduled while in a event listener.
6357 // Test that a debug break can be scheduled while in a message handler. 5284 TEST(DebugBreakInEventListener) {
6358 TEST(DebugBreakInMessageHandler) {
6359 i::FLAG_turbo_inlining = false; // Make sure g is not inlined into f. 5285 i::FLAG_turbo_inlining = false; // Make sure g is not inlined into f.
6360 DebugLocalContext env; 5286 DebugLocalContext env;
6361 v8::HandleScope scope(env->GetIsolate()); 5287 v8::HandleScope scope(env->GetIsolate());
6362 5288
6363 v8::Debug::SetMessageHandler(env->GetIsolate(), DebugBreakMessageHandler); 5289 v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugBreakEventListener);
6364 5290
6365 v8::Local<v8::Context> context = env.context(); 5291 v8::Local<v8::Context> context = env.context();
6366 // Test functions. 5292 // Test functions.
6367 const char* script = "function f() { debugger; g(); } function g() { }"; 5293 const char* script = "function f() { debugger; g(); } function g() { }";
6368 CompileRun(script); 5294 CompileRun(script);
6369 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast( 5295 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
6370 env->Global() 5296 env->Global()
6371 ->Get(context, v8_str(env->GetIsolate(), "f")) 5297 ->Get(context, v8_str(env->GetIsolate(), "f"))
6372 .ToLocalChecked()); 5298 .ToLocalChecked());
6373 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast( 5299 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
6374 env->Global() 5300 env->Global()
6375 ->Get(context, v8_str(env->GetIsolate(), "g")) 5301 ->Get(context, v8_str(env->GetIsolate(), "g"))
6376 .ToLocalChecked()); 5302 .ToLocalChecked());
6377 5303
6378 // Call f then g. The debugger statement in f will cause a break which will 5304 // Call f then g. The debugger statement in f will cause a break which will
6379 // cause another break. 5305 // cause another break.
6380 f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); 5306 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
6381 CHECK_EQ(2, message_handler_break_hit_count); 5307 CHECK_EQ(2, event_listener_break_hit_count);
6382 // Calling g will not cause any additional breaks. 5308 // Calling g will not cause any additional breaks.
6383 g->Call(context, env->Global(), 0, NULL).ToLocalChecked(); 5309 g->Call(context, env->Global(), 0, NULL).ToLocalChecked();
6384 CHECK_EQ(2, message_handler_break_hit_count); 5310 CHECK_EQ(2, event_listener_break_hit_count);
6385 } 5311 }
6386 5312
6387 5313
6388 #ifndef V8_INTERPRETED_REGEXP 5314 #ifndef V8_INTERPRETED_REGEXP
6389 // Debug event handler which gets the function on the top frame and schedules a 5315 // Debug event handler which gets the function on the top frame and schedules a
6390 // break a number of times. 5316 // break a number of times.
6391 static void DebugEventDebugBreak( 5317 static void DebugEventDebugBreak(
6392 const v8::Debug::EventDetails& event_details) { 5318 const v8::Debug::EventDetails& event_details) {
6393 v8::DebugEvent event = event_details.GetEvent(); 5319 v8::DebugEvent event = event_details.GetEvent();
6394 v8::Local<v8::Object> exec_state = event_details.GetExecutionState(); 5320 v8::Local<v8::Object> exec_state = event_details.GetExecutionState();
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
6451 v8::Debug::DebugBreak(env->GetIsolate()); 5377 v8::Debug::DebugBreak(env->GetIsolate());
6452 result = f->Call(context, env->Global(), argc, argv).ToLocalChecked(); 5378 result = f->Call(context, env->Global(), argc, argv).ToLocalChecked();
6453 5379
6454 // Check that there was only one break event. Matching RegExp should not 5380 // Check that there was only one break event. Matching RegExp should not
6455 // cause Break events. 5381 // cause Break events.
6456 CHECK_EQ(1, break_point_hit_count); 5382 CHECK_EQ(1, break_point_hit_count);
6457 CHECK_EQ(0, strcmp("f", last_function_hit)); 5383 CHECK_EQ(0, strcmp("f", last_function_hit));
6458 } 5384 }
6459 #endif // V8_INTERPRETED_REGEXP 5385 #endif // V8_INTERPRETED_REGEXP
6460 5386
5387 // Test which creates a context and sets embedder data on it. Checks that this
5388 // data is set correctly and that when the debug event listener is called for
5389 // break event in an eval statement the expected context is the one returned by
5390 // Message.GetEventContext.
5391 TEST(EvalContextData) {
5392 v8::HandleScope scope(CcTest::isolate());
6461 5393
6462 // Common part of EvalContextData and NestedBreakEventContextData tests.
6463 static void ExecuteScriptForContextCheck(
6464 v8::Debug::MessageHandler message_handler) {
6465 // Create a context.
6466 v8::Local<v8::Context> context_1; 5394 v8::Local<v8::Context> context_1;
6467 v8::Local<v8::ObjectTemplate> global_template = 5395 v8::Local<v8::ObjectTemplate> global_template =
6468 v8::Local<v8::ObjectTemplate>(); 5396 v8::Local<v8::ObjectTemplate>();
6469 context_1 = 5397 context_1 =
6470 v8::Context::New(CcTest::isolate(), NULL, global_template); 5398 v8::Context::New(CcTest::isolate(), NULL, global_template);
6471 5399
6472 v8::Debug::SetMessageHandler(CcTest::isolate(), message_handler); 5400 v8::Debug::SetDebugEventListener(CcTest::isolate(),
5401 ContextCheckEventListener);
6473 5402
6474 // Default data value is undefined. 5403 // Default data value is undefined.
6475 CHECK(context_1->GetEmbedderData(0)->IsUndefined()); 5404 CHECK(context_1->GetEmbedderData(0)->IsUndefined());
6476 5405
6477 // Set and check a data value. 5406 // Set and check a data value.
6478 v8::Local<v8::String> data_1 = v8_str(CcTest::isolate(), "1"); 5407 v8::Local<v8::String> data_1 = v8_str(CcTest::isolate(), "1");
6479 context_1->SetEmbedderData(0, data_1); 5408 context_1->SetEmbedderData(0, data_1);
6480 CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1)); 5409 CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
6481 5410
6482 // Simple test function with eval that causes a break. 5411 // Simple test function with eval that causes a break.
6483 const char* source = "function f() { eval('debugger;'); }"; 5412 const char* source = "function f() { eval('debugger;'); }";
6484 5413
6485 // Enter and run function in the context. 5414 // Enter and run function in the context.
6486 { 5415 {
6487 v8::Context::Scope context_scope(context_1); 5416 v8::Context::Scope context_scope(context_1);
6488 expected_context = context_1; 5417 expected_context = context_1;
6489 expected_context_data = data_1; 5418 expected_context_data = data_1;
6490 v8::Local<v8::Function> f = CompileFunction(CcTest::isolate(), source, "f"); 5419 v8::Local<v8::Function> f = CompileFunction(CcTest::isolate(), source, "f");
6491 f->Call(context_1, context_1->Global(), 0, NULL).ToLocalChecked(); 5420 f->Call(context_1, context_1->Global(), 0, NULL).ToLocalChecked();
6492 } 5421 }
6493 5422
6494 v8::Debug::SetMessageHandler(CcTest::isolate(), nullptr); 5423 v8::Debug::SetDebugEventListener(CcTest::isolate(), nullptr);
6495 }
6496
6497
6498 // Test which creates a context and sets embedder data on it. Checks that this
6499 // data is set correctly and that when the debug message handler is called for
6500 // break event in an eval statement the expected context is the one returned by
6501 // Message.GetEventContext.
6502 TEST(EvalContextData) {
6503 v8::HandleScope scope(CcTest::isolate());
6504
6505 ExecuteScriptForContextCheck(ContextCheckMessageHandler);
6506 5424
6507 // One time compile event and one time break event. 5425 // One time compile event and one time break event.
6508 CHECK_GT(message_handler_hit_count, 2); 5426 CHECK_GT(event_listener_hit_count, 2);
6509 CheckDebuggerUnloaded(CcTest::isolate());
6510 }
6511
6512
6513 static bool sent_eval = false;
6514 static int break_count = 0;
6515 static int continue_command_send_count = 0;
6516 // Check that the expected context is the one generating the debug event
6517 // including the case of nested break event.
6518 static void DebugEvalContextCheckMessageHandler(
6519 const v8::Debug::Message& message) {
6520 CHECK(message.GetEventContext() == expected_context);
6521 CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals(
6522 expected_context_data));
6523 message_handler_hit_count++;
6524
6525 static char print_buffer[1000];
6526 v8::String::Value json(message.GetJSON());
6527 Utf16ToAscii(*json, json.length(), print_buffer);
6528
6529 v8::Isolate* isolate = message.GetIsolate();
6530 if (IsBreakEventMessage(print_buffer)) {
6531 break_count++;
6532 if (!sent_eval) {
6533 sent_eval = true;
6534
6535 const int kBufferSize = 1000;
6536 uint16_t buffer[kBufferSize];
6537 const char* eval_command =
6538 "{\"seq\":0,"
6539 "\"type\":\"request\","
6540 "\"command\":\"evaluate\","
6541 "\"arguments\":{\"expression\":\"debugger;\","
6542 "\"global\":true,\"disable_break\":false}}";
6543
6544 // Send evaluate command.
6545 v8::Debug::SendCommand(
6546 isolate, buffer, AsciiToUtf16(eval_command, buffer));
6547 return;
6548 } else {
6549 // It's a break event caused by the evaluation request above.
6550 SendContinueCommand();
6551 continue_command_send_count++;
6552 }
6553 } else if (IsEvaluateResponseMessage(print_buffer) &&
6554 continue_command_send_count < 2) {
6555 // Response to the evaluation request. We're still on the breakpoint so
6556 // send continue.
6557 SendContinueCommand();
6558 continue_command_send_count++;
6559 }
6560 }
6561
6562
6563 // Tests that context returned for break event is correct when the event occurs
6564 // in 'evaluate' debugger request.
6565 TEST(NestedBreakEventContextData) {
6566 v8::HandleScope scope(CcTest::isolate());
6567 break_count = 0;
6568 message_handler_hit_count = 0;
6569
6570 ExecuteScriptForContextCheck(DebugEvalContextCheckMessageHandler);
6571
6572 // One time compile event and two times break event.
6573 CHECK_GT(message_handler_hit_count, 3);
6574
6575 // One break from the source and another from the evaluate request.
6576 CHECK_EQ(break_count, 2);
6577 CheckDebuggerUnloaded(CcTest::isolate()); 5427 CheckDebuggerUnloaded(CcTest::isolate());
6578 } 5428 }
6579 5429
6580 5430
6581 // Debug event listener which counts the after compile events. 5431 // Debug event listener which counts the after compile events.
6582 int after_compile_message_count = 0; 5432 int after_compile_event_count = 0;
6583 static void AfterCompileMessageHandler(const v8::Debug::Message& message) { 5433 static void AfterCompileEventListener(const v8::Debug::EventDetails& details) {
6584 // Count the number of scripts collected. 5434 // Count the number of scripts collected.
6585 if (message.IsEvent()) { 5435 if (details.GetEvent() == v8::AfterCompile) {
6586 if (message.GetEvent() == v8::AfterCompile) { 5436 after_compile_event_count++;
6587 after_compile_message_count++;
6588 } else if (message.GetEvent() == v8::Break) {
6589 SendContinueCommand();
6590 }
6591 } 5437 }
6592 } 5438 }
6593 5439
6594 5440
6595 // Tests that after compile event is sent as many times as there are scripts 5441 // Tests that after compile event is sent as many times as there are scripts
6596 // compiled. 5442 // compiled.
6597 TEST(AfterCompileMessageWhenMessageHandlerIsReset) { 5443 TEST(AfterCompileEventWhenEventListenerIsReset) {
6598 DebugLocalContext env; 5444 DebugLocalContext env;
6599 v8::HandleScope scope(env->GetIsolate()); 5445 v8::HandleScope scope(env->GetIsolate());
6600 v8::Local<v8::Context> context = env.context(); 5446 v8::Local<v8::Context> context = env.context();
6601 after_compile_message_count = 0;
6602 const char* script = "var a=1"; 5447 const char* script = "var a=1";
6603 5448
6604 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); 5449 v8::Debug::SetDebugEventListener(env->GetIsolate(),
5450 AfterCompileEventListener);
6605 v8::Script::Compile(context, v8_str(env->GetIsolate(), script)) 5451 v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
6606 .ToLocalChecked() 5452 .ToLocalChecked()
6607 ->Run(context) 5453 ->Run(context)
6608 .ToLocalChecked(); 5454 .ToLocalChecked();
6609 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); 5455 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
6610 5456
6611 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); 5457 v8::Debug::SetDebugEventListener(env->GetIsolate(),
5458 AfterCompileEventListener);
6612 v8::Debug::DebugBreak(env->GetIsolate()); 5459 v8::Debug::DebugBreak(env->GetIsolate());
6613 v8::Script::Compile(context, v8_str(env->GetIsolate(), script)) 5460 v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
6614 .ToLocalChecked() 5461 .ToLocalChecked()
6615 ->Run(context) 5462 ->Run(context)
6616 .ToLocalChecked(); 5463 .ToLocalChecked();
6617 5464
6618 // Setting listener to NULL should cause debugger unload. 5465 // Setting listener to NULL should cause debugger unload.
6619 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); 5466 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
6620 CheckDebuggerUnloaded(env->GetIsolate()); 5467 CheckDebuggerUnloaded(env->GetIsolate());
6621 5468
6622 // Compilation cache should be disabled when debugger is active. 5469 // Compilation cache should be disabled when debugger is active.
6623 CHECK_EQ(2, after_compile_message_count); 5470 CHECK_EQ(2, after_compile_event_count);
6624 } 5471 }
6625 5472
6626 5473
6627 // Syntax error event handler which counts a number of events. 5474 // Syntax error event handler which counts a number of events.
6628 int compile_error_event_count = 0; 5475 int compile_error_event_count = 0;
6629 5476
6630 static void CompileErrorEventCounterClear() { 5477 static void CompileErrorEventCounterClear() {
6631 compile_error_event_count = 0; 5478 compile_error_event_count = 0;
6632 } 5479 }
6633 5480
6634 static void CompileErrorEventCounter( 5481 static void CompileErrorEventCounter(
6635 const v8::Debug::EventDetails& event_details) { 5482 const v8::Debug::EventDetails& event_details) {
6636 v8::DebugEvent event = event_details.GetEvent(); 5483 v8::DebugEvent event = event_details.GetEvent();
6637 5484
6638 if (event == v8::CompileError) { 5485 if (event == v8::CompileError) {
6639 compile_error_event_count++; 5486 compile_error_event_count++;
6640 } 5487 }
6641 } 5488 }
6642 5489
6643 5490
6644 // Tests that syntax error event is sent as many times as there are scripts 5491 // Tests that syntax error event is sent as many times as there are scripts
6645 // with syntax error compiled. 5492 // with syntax error compiled.
6646 TEST(SyntaxErrorMessageOnSyntaxException) { 5493 TEST(SyntaxErrorEventOnSyntaxException) {
6647 DebugLocalContext env; 5494 DebugLocalContext env;
6648 v8::HandleScope scope(env->GetIsolate()); 5495 v8::HandleScope scope(env->GetIsolate());
6649 5496
6650 // For this test, we want to break on uncaught exceptions: 5497 // For this test, we want to break on uncaught exceptions:
6651 ChangeBreakOnException(false, true); 5498 ChangeBreakOnException(false, true);
6652 5499
6653 v8::Debug::SetDebugEventListener(env->GetIsolate(), CompileErrorEventCounter); 5500 v8::Debug::SetDebugEventListener(env->GetIsolate(), CompileErrorEventCounter);
6654 v8::Local<v8::Context> context = env.context(); 5501 v8::Local<v8::Context> context = env.context();
6655 5502
6656 CompileErrorEventCounterClear(); 5503 CompileErrorEventCounterClear();
(...skipping 21 matching lines...) Expand all
6678 v8::Script::Compile(context, 5525 v8::Script::Compile(context,
6679 v8_str(env->GetIsolate(), "new RegExp('/\\/\\\\');")) 5526 v8_str(env->GetIsolate(), "new RegExp('/\\/\\\\');"))
6680 .ToLocalChecked(); 5527 .ToLocalChecked();
6681 CHECK_EQ(3, compile_error_event_count); 5528 CHECK_EQ(3, compile_error_event_count);
6682 5529
6683 v8::Script::Compile(context, v8_str(env->GetIsolate(), "throw 1;")) 5530 v8::Script::Compile(context, v8_str(env->GetIsolate(), "throw 1;"))
6684 .ToLocalChecked(); 5531 .ToLocalChecked();
6685 CHECK_EQ(3, compile_error_event_count); 5532 CHECK_EQ(3, compile_error_event_count);
6686 } 5533 }
6687 5534
6688 5535 // Tests that break event is sent when event listener is reset.
6689 // Tests that break event is sent when message handler is reset. 5536 TEST(BreakEventWhenEventListenerIsReset) {
6690 TEST(BreakMessageWhenMessageHandlerIsReset) {
6691 DebugLocalContext env; 5537 DebugLocalContext env;
6692 v8::HandleScope scope(env->GetIsolate()); 5538 v8::HandleScope scope(env->GetIsolate());
6693 v8::Local<v8::Context> context = env.context(); 5539 v8::Local<v8::Context> context = env.context();
6694 after_compile_message_count = 0;
jgruber 2016/11/24 09:53:08 Why does this test work if after_compile_event_cou
Yang 2016/11/24 09:56:17 cctests are supposed to be called one by one, to p
6695 const char* script = "function f() {};"; 5540 const char* script = "function f() {};";
6696 5541
6697 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); 5542 v8::Debug::SetDebugEventListener(env->GetIsolate(),
5543 AfterCompileEventListener);
6698 v8::Script::Compile(context, v8_str(env->GetIsolate(), script)) 5544 v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
6699 .ToLocalChecked() 5545 .ToLocalChecked()
6700 ->Run(context) 5546 ->Run(context)
6701 .ToLocalChecked(); 5547 .ToLocalChecked();
6702 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); 5548 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
6703 5549
6704 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); 5550 v8::Debug::SetDebugEventListener(env->GetIsolate(),
5551 AfterCompileEventListener);
6705 v8::Debug::DebugBreak(env->GetIsolate()); 5552 v8::Debug::DebugBreak(env->GetIsolate());
6706 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast( 5553 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
6707 env->Global() 5554 env->Global()
6708 ->Get(context, v8_str(env->GetIsolate(), "f")) 5555 ->Get(context, v8_str(env->GetIsolate(), "f"))
6709 .ToLocalChecked()); 5556 .ToLocalChecked());
6710 f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); 5557 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
6711 5558
6712 // Setting message handler to NULL should cause debugger unload. 5559 // Setting event listener to NULL should cause debugger unload.
6713 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); 5560 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
6714 CheckDebuggerUnloaded(env->GetIsolate()); 5561 CheckDebuggerUnloaded(env->GetIsolate());
6715 5562
6716 // Compilation cache should be disabled when debugger is active. 5563 // Compilation cache should be disabled when debugger is active.
6717 CHECK_EQ(1, after_compile_message_count); 5564 CHECK_EQ(1, after_compile_event_count);
6718 } 5565 }
6719 5566
6720 5567
6721 static int exception_event_count = 0; 5568 static int exception_event_count = 0;
6722 static void ExceptionMessageHandler(const v8::Debug::Message& message) { 5569 static void ExceptionEventListener(const v8::Debug::EventDetails& details) {
6723 if (message.IsEvent() && message.GetEvent() == v8::Exception) { 5570 if (details.GetEvent() == v8::Exception) exception_event_count++;
6724 exception_event_count++;
6725 SendContinueCommand();
6726 }
6727 } 5571 }
6728 5572
6729 5573 // Tests that exception event is sent when event listener is reset.
6730 // Tests that exception event is sent when message handler is reset. 5574 TEST(ExceptionEventWhenEventListenerIsReset) {
6731 TEST(ExceptionMessageWhenMessageHandlerIsReset) {
6732 DebugLocalContext env; 5575 DebugLocalContext env;
6733 v8::HandleScope scope(env->GetIsolate()); 5576 v8::HandleScope scope(env->GetIsolate());
6734 5577
6735 v8::Local<v8::Context> context = env.context(); 5578 v8::Local<v8::Context> context = env.context();
6736 // For this test, we want to break on uncaught exceptions: 5579 // For this test, we want to break on uncaught exceptions:
6737 ChangeBreakOnException(false, true); 5580 ChangeBreakOnException(false, true);
6738 5581
6739 exception_event_count = 0; 5582 exception_event_count = 0;
6740 const char* script = "function f() {throw new Error()};"; 5583 const char* script = "function f() {throw new Error()};";
6741 5584
6742 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); 5585 v8::Debug::SetDebugEventListener(env->GetIsolate(),
5586 AfterCompileEventListener);
6743 v8::Script::Compile(context, v8_str(env->GetIsolate(), script)) 5587 v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
6744 .ToLocalChecked() 5588 .ToLocalChecked()
6745 ->Run(context) 5589 ->Run(context)
6746 .ToLocalChecked(); 5590 .ToLocalChecked();
6747 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); 5591 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
6748 5592
6749 v8::Debug::SetMessageHandler(env->GetIsolate(), ExceptionMessageHandler); 5593 v8::Debug::SetDebugEventListener(env->GetIsolate(), ExceptionEventListener);
6750 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast( 5594 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
6751 env->Global() 5595 env->Global()
6752 ->Get(context, v8_str(env->GetIsolate(), "f")) 5596 ->Get(context, v8_str(env->GetIsolate(), "f"))
6753 .ToLocalChecked()); 5597 .ToLocalChecked());
6754 CHECK(f->Call(context, env->Global(), 0, NULL).IsEmpty()); 5598 CHECK(f->Call(context, env->Global(), 0, NULL).IsEmpty());
6755 5599
6756 // Setting message handler to NULL should cause debugger unload. 5600 // Setting event listener to NULL should cause debugger unload.
6757 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); 5601 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
6758 CheckDebuggerUnloaded(env->GetIsolate()); 5602 CheckDebuggerUnloaded(env->GetIsolate());
6759 5603
6760 CHECK_EQ(1, exception_event_count); 5604 CHECK_EQ(1, exception_event_count);
6761 } 5605 }
6762 5606
6763 5607
6764 // Tests after compile event is sent when there are some provisional 5608 // Tests after compile event is sent when there are some provisional
6765 // breakpoints out of the scripts lines range. 5609 // breakpoints out of the scripts lines range.
6766 TEST(ProvisionalBreakpointOnLineOutOfRange) { 5610 TEST(ProvisionalBreakpointOnLineOutOfRange) {
6767 DebugLocalContext env; 5611 DebugLocalContext env;
6768 v8::HandleScope scope(env->GetIsolate()); 5612 v8::HandleScope scope(env->GetIsolate());
6769 env.ExposeDebug(); 5613 env.ExposeDebug();
6770 const char* script = "function f() {};"; 5614 const char* script = "function f() {};";
6771 const char* resource_name = "test_resource"; 5615 const char* resource_name = "test_resource";
6772 5616
6773 v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); 5617 v8::Debug::SetDebugEventListener(env->GetIsolate(),
5618 AfterCompileEventListener);
6774 v8::Local<v8::Context> context = env.context(); 5619 v8::Local<v8::Context> context = env.context();
6775 5620
6776 // Set a couple of provisional breakpoint on lines out of the script lines 5621 // Set a couple of provisional breakpoint on lines out of the script lines
6777 // range. 5622 // range.
6778 int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, 5623 int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name,
6779 3, -1 /* no column */); 5624 3, -1 /* no column */);
6780 int sbp2 = 5625 int sbp2 =
6781 SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, 5, 5); 5626 SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, 5, 5);
6782 5627
6783 after_compile_message_count = 0; 5628 after_compile_event_count = 0;
6784 5629
6785 v8::ScriptOrigin origin(v8_str(env->GetIsolate(), resource_name), 5630 v8::ScriptOrigin origin(v8_str(env->GetIsolate(), resource_name),
6786 v8::Integer::New(env->GetIsolate(), 10), 5631 v8::Integer::New(env->GetIsolate(), 10),
6787 v8::Integer::New(env->GetIsolate(), 1)); 5632 v8::Integer::New(env->GetIsolate(), 1));
6788 // Compile a script whose first line number is greater than the breakpoints' 5633 // Compile a script whose first line number is greater than the breakpoints'
6789 // lines. 5634 // lines.
6790 v8::Script::Compile(context, v8_str(env->GetIsolate(), script), &origin) 5635 v8::Script::Compile(context, v8_str(env->GetIsolate(), script), &origin)
6791 .ToLocalChecked() 5636 .ToLocalChecked()
6792 ->Run(context) 5637 ->Run(context)
6793 .ToLocalChecked(); 5638 .ToLocalChecked();
6794 5639
6795 // If the script is compiled successfully there is exactly one after compile 5640 // If the script is compiled successfully there is exactly one after compile
6796 // event. In case of an exception in debugger code after compile event is not 5641 // event. In case of an exception in debugger code after compile event is not
6797 // sent. 5642 // sent.
6798 CHECK_EQ(1, after_compile_message_count); 5643 CHECK_EQ(1, after_compile_event_count);
6799 5644
6800 ClearBreakPointFromJS(env->GetIsolate(), sbp1); 5645 ClearBreakPointFromJS(env->GetIsolate(), sbp1);
6801 ClearBreakPointFromJS(env->GetIsolate(), sbp2); 5646 ClearBreakPointFromJS(env->GetIsolate(), sbp2);
6802 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); 5647 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
5648 CheckDebuggerUnloaded(env->GetIsolate());
6803 } 5649 }
6804 5650
6805 5651 static void BreakEventListener(const v8::Debug::EventDetails& details) {
6806 static void BreakMessageHandler(const v8::Debug::Message& message) { 5652 if (details.GetEvent() == v8::Break) break_point_hit_count++;
6807 i::Isolate* isolate = CcTest::i_isolate();
6808 if (message.IsEvent() && message.GetEvent() == v8::Break) {
6809 // Count the number of breaks.
6810 break_point_hit_count++;
6811
6812 i::HandleScope scope(isolate);
6813 message.GetJSON();
6814
6815 SendContinueCommand();
6816 } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) {
6817 i::HandleScope scope(isolate);
6818
6819 int current_count = break_point_hit_count;
6820
6821 // Force serialization to trigger some internal JS execution.
6822 message.GetJSON();
6823
6824 CHECK_EQ(current_count, break_point_hit_count);
6825 }
6826 } 5653 }
6827 5654
6828 5655
6829 // Test that if DebugBreak is forced it is ignored when code from 5656 // Test that if DebugBreak is forced it is ignored when code from
6830 // debug-delay.js is executed. 5657 // debug-delay.js is executed.
6831 TEST(NoDebugBreakInAfterCompileMessageHandler) { 5658 TEST(NoDebugBreakInAfterCompileEventListener) {
6832 DebugLocalContext env; 5659 DebugLocalContext env;
6833 v8::HandleScope scope(env->GetIsolate()); 5660 v8::HandleScope scope(env->GetIsolate());
6834 v8::Local<v8::Context> context = env.context(); 5661 v8::Local<v8::Context> context = env.context();
6835 5662
6836 // Register a debug event listener which sets the break flag and counts. 5663 // Register a debug event listener which sets the break flag and counts.
6837 v8::Debug::SetMessageHandler(env->GetIsolate(), BreakMessageHandler); 5664 v8::Debug::SetDebugEventListener(env->GetIsolate(), BreakEventListener);
6838 5665
6839 // Set the debug break flag. 5666 // Set the debug break flag.
6840 v8::Debug::DebugBreak(env->GetIsolate()); 5667 v8::Debug::DebugBreak(env->GetIsolate());
6841 5668
6842 // Create a function for testing stepping. 5669 // Create a function for testing stepping.
6843 const char* src = "function f() { eval('var x = 10;'); } "; 5670 const char* src = "function f() { eval('var x = 10;'); } ";
6844 v8::Local<v8::Function> f = CompileFunction(&env, src, "f"); 5671 v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
6845 5672
6846 // There should be only one break event. 5673 // There should be only one break event.
6847 CHECK_EQ(1, break_point_hit_count); 5674 CHECK_EQ(1, break_point_hit_count);
6848 5675
6849 // Set the debug break flag again. 5676 // Set the debug break flag again.
6850 v8::Debug::DebugBreak(env->GetIsolate()); 5677 v8::Debug::DebugBreak(env->GetIsolate());
6851 f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); 5678 f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
6852 // There should be one more break event when the script is evaluated in 'f'. 5679 // There should be one more break event when the script is evaluated in 'f'.
6853 CHECK_EQ(2, break_point_hit_count); 5680 CHECK_EQ(2, break_point_hit_count);
6854 5681
6855 // Get rid of the debug message handler. 5682 // Get rid of the debug event listener.
6856 v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); 5683 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
6857 CheckDebuggerUnloaded(env->GetIsolate()); 5684 CheckDebuggerUnloaded(env->GetIsolate());
6858 } 5685 }
6859 5686
6860 5687
6861 static int counting_message_handler_counter;
6862
6863 static void CountingMessageHandler(const v8::Debug::Message& message) {
6864 if (message.IsResponse()) counting_message_handler_counter++;
6865 }
6866
6867
6868 // Test that debug messages get processed when ProcessDebugMessages is called.
6869 TEST(ProcessDebugMessages) {
6870 DebugLocalContext env;
6871 v8::Isolate* isolate = env->GetIsolate();
6872 v8::HandleScope scope(isolate);
6873
6874 counting_message_handler_counter = 0;
6875
6876 v8::Debug::SetMessageHandler(isolate, CountingMessageHandler);
6877
6878 const int kBufferSize = 1000;
6879 uint16_t buffer[kBufferSize];
6880 const char* scripts_command =
6881 "{\"seq\":0,"
6882 "\"type\":\"request\","
6883 "\"command\":\"scripts\"}";
6884
6885 // Send scripts command.
6886 v8::Debug::SendCommand(
6887 isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6888
6889 CHECK_EQ(0, counting_message_handler_counter);
6890 v8::Debug::ProcessDebugMessages(isolate);
6891 // At least one message should come
6892 CHECK_GE(counting_message_handler_counter, 1);
6893
6894 counting_message_handler_counter = 0;
6895
6896 v8::Debug::SendCommand(
6897 isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6898 v8::Debug::SendCommand(
6899 isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6900 CHECK_EQ(0, counting_message_handler_counter);
6901 v8::Debug::ProcessDebugMessages(isolate);
6902 // At least two messages should come
6903 CHECK_GE(counting_message_handler_counter, 2);
6904
6905 // Get rid of the debug message handler.
6906 v8::Debug::SetMessageHandler(isolate, nullptr);
6907 CheckDebuggerUnloaded(isolate);
6908 }
6909
6910
6911 class SendCommandThread;
6912 static SendCommandThread* send_command_thread_ = NULL;
6913
6914
6915 class SendCommandThread : public v8::base::Thread {
6916 public:
6917 explicit SendCommandThread(v8::Isolate* isolate)
6918 : Thread(Options("SendCommandThread")),
6919 semaphore_(0),
6920 isolate_(isolate) {}
6921
6922 static void CountingAndSignallingMessageHandler(
6923 const v8::Debug::Message& message) {
6924 if (message.IsResponse()) {
6925 counting_message_handler_counter++;
6926 send_command_thread_->semaphore_.Signal();
6927 }
6928 }
6929
6930 virtual void Run() {
6931 semaphore_.Wait();
6932 const int kBufferSize = 1000;
6933 uint16_t buffer[kBufferSize];
6934 const char* scripts_command =
6935 "{\"seq\":0,"
6936 "\"type\":\"request\","
6937 "\"command\":\"scripts\"}";
6938 int length = AsciiToUtf16(scripts_command, buffer);
6939 // Send scripts command.
6940
6941 for (int i = 0; i < 20; i++) {
6942 v8::base::ElapsedTimer timer;
6943 timer.Start();
6944 CHECK_EQ(i, counting_message_handler_counter);
6945 // Queue debug message.
6946 v8::Debug::SendCommand(isolate_, buffer, length);
6947 // Wait for the message handler to pick up the response.
6948 semaphore_.Wait();
6949 i::PrintF("iteration %d took %f ms\n", i,
6950 timer.Elapsed().InMillisecondsF());
6951 }
6952
6953 isolate_->TerminateExecution();
6954 }
6955
6956 void StartSending() { semaphore_.Signal(); }
6957
6958 private:
6959 v8::base::Semaphore semaphore_;
6960 v8::Isolate* isolate_;
6961 };
6962
6963
6964 static void StartSendingCommands(
6965 const v8::FunctionCallbackInfo<v8::Value>& info) {
6966 send_command_thread_->StartSending();
6967 }
6968
6969
6970 TEST(ProcessDebugMessagesThreaded) {
6971 DebugLocalContext env;
6972 v8::Isolate* isolate = env->GetIsolate();
6973 v8::HandleScope scope(isolate);
6974 v8::Local<v8::Context> context = env.context();
6975
6976 counting_message_handler_counter = 0;
6977
6978 v8::Debug::SetMessageHandler(
6979 isolate, SendCommandThread::CountingAndSignallingMessageHandler);
6980 send_command_thread_ = new SendCommandThread(isolate);
6981 send_command_thread_->Start();
6982
6983 v8::Local<v8::FunctionTemplate> start =
6984 v8::FunctionTemplate::New(isolate, StartSendingCommands);
6985 CHECK(env->Global()
6986 ->Set(context, v8_str("start"),
6987 start->GetFunction(context).ToLocalChecked())
6988 .FromJust());
6989
6990 CompileRun("start(); while (true) { }");
6991
6992 CHECK_EQ(20, counting_message_handler_counter);
6993
6994 v8::Debug::SetMessageHandler(isolate, nullptr);
6995 CheckDebuggerUnloaded(isolate);
6996 }
6997
6998
6999 struct BacktraceData {
7000 static int frame_counter;
7001 static void MessageHandler(const v8::Debug::Message& message) {
7002 char print_buffer[1000];
7003 v8::String::Value json(message.GetJSON());
7004 Utf16ToAscii(*json, json.length(), print_buffer, 1000);
7005
7006 if (strstr(print_buffer, "backtrace") == NULL) {
7007 return;
7008 }
7009 frame_counter = GetTotalFramesInt(print_buffer);
7010 }
7011 };
7012
7013 int BacktraceData::frame_counter;
7014
7015
7016 // Test that debug messages get processed when ProcessDebugMessages is called.
7017 TEST(Backtrace) {
7018 DebugLocalContext env;
7019 v8::Isolate* isolate = env->GetIsolate();
7020 v8::HandleScope scope(isolate);
7021 v8::Local<v8::Context> context = env.context();
7022
7023 v8::Debug::SetMessageHandler(isolate, BacktraceData::MessageHandler);
7024
7025 const int kBufferSize = 1000;
7026 uint16_t buffer[kBufferSize];
7027 const char* scripts_command =
7028 "{\"seq\":0,"
7029 "\"type\":\"request\","
7030 "\"command\":\"backtrace\"}";
7031
7032 // Check backtrace from ProcessDebugMessages.
7033 BacktraceData::frame_counter = -10;
7034 v8::Debug::SendCommand(
7035 isolate,
7036 buffer,
7037 AsciiToUtf16(scripts_command, buffer),
7038 NULL);
7039 v8::Debug::ProcessDebugMessages(isolate);
7040 CHECK_EQ(BacktraceData::frame_counter, 0);
7041
7042 v8::Local<v8::String> void0 = v8_str(env->GetIsolate(), "void(0)");
7043 v8::Local<v8::Script> script = CompileWithOrigin(void0, void0);
7044
7045 // Check backtrace from "void(0)" script.
7046 BacktraceData::frame_counter = -10;
7047 v8::Debug::SendCommand(
7048 isolate,
7049 buffer,
7050 AsciiToUtf16(scripts_command, buffer),
7051 NULL);
7052 script->Run(context).ToLocalChecked();
7053 CHECK_EQ(BacktraceData::frame_counter, 1);
7054
7055 // Get rid of the debug message handler.
7056 v8::Debug::SetMessageHandler(isolate, nullptr);
7057 CheckDebuggerUnloaded(isolate);
7058 }
7059
7060
7061 TEST(GetMirror) { 5688 TEST(GetMirror) {
7062 DebugLocalContext env; 5689 DebugLocalContext env;
7063 v8::Isolate* isolate = env->GetIsolate(); 5690 v8::Isolate* isolate = env->GetIsolate();
7064 v8::HandleScope scope(isolate); 5691 v8::HandleScope scope(isolate);
7065 v8::Local<v8::Context> context = env.context(); 5692 v8::Local<v8::Context> context = env.context();
7066 v8::Local<v8::Value> obj = 5693 v8::Local<v8::Value> obj =
7067 v8::Debug::GetMirror(context, v8_str(isolate, "hodja")).ToLocalChecked(); 5694 v8::Debug::GetMirror(context, v8_str(isolate, "hodja")).ToLocalChecked();
7068 v8::ScriptCompiler::Source source(v8_str( 5695 v8::ScriptCompiler::Source source(v8_str(
7069 "function runTest(mirror) {" 5696 "function runTest(mirror) {"
7070 " return mirror.isString() && (mirror.length() == 5);" 5697 " return mirror.isString() && (mirror.length() == 5);"
(...skipping 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after
8230 "function foo() {\n" 6857 "function foo() {\n"
8231 " try { throw new Error(); } catch (e) {}\n" 6858 " try { throw new Error(); } catch (e) {}\n"
8232 "}\n" 6859 "}\n"
8233 "debugger;\n" 6860 "debugger;\n"
8234 "foo();\n" 6861 "foo();\n"
8235 "foo();\n"); 6862 "foo();\n");
8236 6863
8237 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); 6864 v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
8238 CHECK_EQ(break_point_hit_count, 4); 6865 CHECK_EQ(break_point_hit_count, 4);
8239 } 6866 }
OLDNEW
« no previous file with comments | « test/cctest/cctest.status ('k') | test/inspector/runtime/evaluate-empty-stack.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698