New version of v8 from bleeding edge at revision 3649
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 5b72193..cd0da1b 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -443,6 +443,9 @@
 
 // Check that the debugger has been fully unloaded.
 static void CheckDebuggerUnloaded(bool check_functions = false) {
+  // Let debugger to unload itself synchronously
+  v8::Debug::ProcessDebugMessages();
+
   v8::internal::CheckDebuggerUnloaded(check_functions);
 }
 
@@ -2160,6 +2163,155 @@
   CheckDebuggerUnloaded();
 }
 
+// Copies a C string to a 16-bit string.  Does not check for buffer overflow.
+// Does not use the V8 engine to convert strings, so it can be used
+// in any thread.  Returns the length of the string.
+int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
+  int i;
+  for (i = 0; input_buffer[i] != '\0'; ++i) {
+    // ASCII does not use chars > 127, but be careful anyway.
+    output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
+  }
+  output_buffer[i] = 0;
+  return i;
+}
+
+// Copies a 16-bit string to a C string by dropping the high byte of
+// each character.  Does not check for buffer overflow.
+// Can be used in any thread.  Requires string length as an input.
+int Utf16ToAscii(const uint16_t* input_buffer, int length,
+                 char* output_buffer, int output_len = -1) {
+  if (output_len >= 0) {
+    if (length > output_len - 1) {
+      length = output_len - 1;
+    }
+  }
+
+  for (int i = 0; i < length; ++i) {
+    output_buffer[i] = static_cast<char>(input_buffer[i]);
+  }
+  output_buffer[length] = '\0';
+  return length;
+}
+
+
+// We match parts of the message to get evaluate result int value.
+bool GetEvaluateStringResult(char *message, char* buffer, int buffer_size) {
+  const char* value = "\"value\":";
+  char* pos = strstr(message, value);
+  if (pos == NULL) {
+    return false;
+  }
+  Vector<char> buf(buffer, buffer_size);
+  OS::StrNCpy(buf, pos, buffer_size);
+  buffer[buffer_size - 1] = '\0';
+  return true;
+}
+
+
+struct EvaluateResult {
+  static const int kBufferSize = 20;
+  char buffer[kBufferSize];
+};
+
+struct DebugProcessDebugMessagesData {
+  static const int kArraySize = 5;
+  int counter;
+  EvaluateResult results[kArraySize];
+
+  void reset() {
+    counter = 0;
+  }
+  EvaluateResult* current() {
+    return &results[counter % kArraySize];
+  }
+  void next() {
+    counter++;
+  }
+};
+
+DebugProcessDebugMessagesData process_debug_messages_data;
+
+static void DebugProcessDebugMessagesHandler(
+    const uint16_t* message,
+    int length,
+    v8::Debug::ClientData* client_data) {
+
+  const int kBufferSize = 100000;
+  char print_buffer[kBufferSize];
+  Utf16ToAscii(message, length, print_buffer, kBufferSize);
+
+  EvaluateResult* array_item = process_debug_messages_data.current();
+
+  bool res = GetEvaluateStringResult(print_buffer,
+                                     array_item->buffer,
+                                     EvaluateResult::kBufferSize);
+  if (res) {
+    process_debug_messages_data.next();
+  }
+}
+
+// Test that the evaluation of expressions works even from ProcessDebugMessages
+// i.e. with empty stack.
+TEST(DebugEvaluateWithoutStack) {
+  v8::Debug::SetMessageHandler(DebugProcessDebugMessagesHandler);
+
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  const char* source =
+      "var v1 = 'Pinguin';\n function getAnimal() { return 'Capy' + 'bara'; }";
+
+  v8::Script::Compile(v8::String::New(source))->Run();
+
+  v8::Debug::ProcessDebugMessages();
+
+  const int kBufferSize = 1000;
+  uint16_t buffer[kBufferSize];
+
+  const char* command_111 = "{\"seq\":111,"
+      "\"type\":\"request\","
+      "\"command\":\"evaluate\","
+      "\"arguments\":{"
+      "    \"global\":true,"
+      "    \"expression\":\"v1\",\"disable_break\":true"
+      "}}";
+
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_111, buffer));
+
+  const char* command_112 = "{\"seq\":112,"
+      "\"type\":\"request\","
+      "\"command\":\"evaluate\","
+      "\"arguments\":{"
+      "    \"global\":true,"
+      "    \"expression\":\"getAnimal()\",\"disable_break\":true"
+      "}}";
+
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_112, buffer));
+
+  const char* command_113 = "{\"seq\":113,"
+     "\"type\":\"request\","
+     "\"command\":\"evaluate\","
+     "\"arguments\":{"
+     "    \"global\":true,"
+     "    \"expression\":\"239 + 566\",\"disable_break\":true"
+     "}}";
+
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_113, buffer));
+
+  v8::Debug::ProcessDebugMessages();
+
+  CHECK_EQ(3, process_debug_messages_data.counter);
+
+  CHECK(strcmp("Pinguin", process_debug_messages_data.results[0].buffer));
+  CHECK(strcmp("Captbara", process_debug_messages_data.results[1].buffer));
+  CHECK(strcmp("805", process_debug_messages_data.results[2].buffer));
+
+  v8::Debug::SetMessageHandler(NULL);
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
 
 // Simple test of the stepping mechanism using only store ICs.
 TEST(DebugStepLinear) {
@@ -3141,6 +3293,39 @@
   CheckDebuggerUnloaded();
 }
 
+static const char* kSimpleExtensionSource =
+  "(function Foo() {"
+  "  return 4;"
+  "})() ";
+
+// http://crbug.com/28933
+// Test that debug break is disabled when bootstrapper is active.
+TEST(NoBreakWhenBootstrapping) {
+  v8::HandleScope scope;
+
+  // Register a debug event listener which sets the break flag and counts.
+  v8::Debug::SetDebugEventListener(DebugEventCounter);
+
+  // Set the debug break flag.
+  v8::Debug::DebugBreak();
+  break_point_hit_count = 0;
+  {
+    // Create a context with an extension to make sure that some JavaScript
+    // code is executed during bootstrapping.
+    v8::RegisterExtension(new v8::Extension("simpletest",
+                                            kSimpleExtensionSource));
+    const char* extension_names[] = { "simpletest" };
+    v8::ExtensionConfiguration extensions(1, extension_names);
+    v8::Persistent<v8::Context> context = v8::Context::New(&extensions);
+    context.Dispose();
+  }
+  // Check that no DebugBreak events occured during the context creation.
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Get rid of the debug event listener.
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
 
 static v8::Handle<v8::Array> NamedEnum(const v8::AccessorInfo&) {
   v8::Handle<v8::Array> result = v8::Array::New(3);
@@ -3557,31 +3742,6 @@
 
 // Support classes
 
-// Copies a C string to a 16-bit string.  Does not check for buffer overflow.
-// Does not use the V8 engine to convert strings, so it can be used
-// in any thread.  Returns the length of the string.
-int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
-  int i;
-  for (i = 0; input_buffer[i] != '\0'; ++i) {
-    // ASCII does not use chars > 127, but be careful anyway.
-    output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
-  }
-  output_buffer[i] = 0;
-  return i;
-}
-
-// Copies a 16-bit string to a C string by dropping the high byte of
-// each character.  Does not check for buffer overflow.
-// Can be used in any thread.  Requires string length as an input.
-int Utf16ToAscii(const uint16_t* input_buffer, int length,
-                 char* output_buffer) {
-  for (int i = 0; i < length; ++i) {
-    output_buffer[i] = static_cast<char>(input_buffer[i]);
-  }
-  output_buffer[length] = '\0';
-  return length;
-}
-
 // Provides synchronization between k threads, where k is an input to the
 // constructor.  The Wait() call blocks a thread until it is called for the
 // k'th time, then all calls return.  Each ThreadBarrier object can only
@@ -5622,6 +5782,51 @@
 }
 
 
+static int counting_message_handler_counter;
+
+static void CountingMessageHandler(const v8::Debug::Message& message) {
+  counting_message_handler_counter++;
+}
+
+// Test that debug messages get processed when ProcessDebugMessages is called.
+TEST(ProcessDebugMessages) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  counting_message_handler_counter = 0;
+
+  v8::Debug::SetMessageHandler2(CountingMessageHandler);
+
+  const int kBufferSize = 1000;
+  uint16_t buffer[kBufferSize];
+  const char* scripts_command =
+    "{\"seq\":0,"
+     "\"type\":\"request\","
+     "\"command\":\"scripts\"}";
+
+  // Send scripts command.
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(scripts_command, buffer));
+
+  CHECK_EQ(0, counting_message_handler_counter);
+  v8::Debug::ProcessDebugMessages();
+  // At least one message should come
+  CHECK_GE(counting_message_handler_counter, 1);
+
+  counting_message_handler_counter = 0;
+
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(scripts_command, buffer));
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(scripts_command, buffer));
+  CHECK_EQ(0, counting_message_handler_counter);
+  v8::Debug::ProcessDebugMessages();
+  // At least two messages should come
+  CHECK_GE(counting_message_handler_counter, 2);
+
+  // Get rid of the debug message handler.
+  v8::Debug::SetMessageHandler2(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
 TEST(GetMirror) {
   v8::HandleScope scope;
   DebugLocalContext env;