}
-// Helper function to check whether the JSON request is a plain break request.
-// This is used form the runtime handling of pending debug requests. If one of
-// the pending requests is a plain break execution should be broken after
-// processing the pending break requests.
-function IsPlainBreakRequest(json_request) {
- try {
- // Convert the JSON string to an object.
- request = %CompileString('(' + json_request + ')', false)();
-
- // Check for break command without arguments.
- return request.command && request.command == "break" && !request.arguments;
- } catch (e) {
- // If there is a exception parsing the JSON request just return false.
- return false;
- }
-}
-
-
Debug.addListener = function(listener, opt_data) {
if (!IS_FUNCTION(listener)) throw new Error('Parameters have wrong types.');
%AddDebugEventListener(listener, opt_data);
}
-bool Debugger::IsPlainBreakRequest(Handle<Object> request) {
- // Get the function IsPlainBreakRequest (defined in debug.js).
- Handle<JSFunction> process_debug_request =
- Handle<JSFunction>(JSFunction::cast(
- Debug::debug_context()->global()->GetProperty(
- *Factory::LookupAsciiSymbol("IsPlainBreakRequest"))));
-
- // Call ProcessDebugRequest expect String result.
- bool caught_exception;
- const int argc = 1;
- Object** argv[argc] = { request.location() };
- Handle<Object> result = Execution::TryCall(process_debug_request,
- Factory::undefined_value(),
- argc, argv,
- &caught_exception);
- if (caught_exception) {
- return false;
- }
- return *result == Heap::true_value();
-}
-
-
void Debugger::OnException(Handle<Object> exception, bool uncaught) {
HandleScope scope;
}
-// Compare a two byte string to an null terminated ASCII string.
-bool DebugMessageThread::TwoByteEqualsAscii(Vector<uint16_t> two_byte,
- const char* ascii) {
- for (int i = 0; i < two_byte.length(); i++) {
- if (ascii[i] == '\0') {
- return false;
- }
- if (two_byte[i] != static_cast<uint16_t>(ascii[i])) {
- return false;
- }
- }
- return ascii[two_byte.length()] == '\0';
-}
-
-
void DebugMessageThread::Run() {
// Sends debug events to an installed debugger message callback.
while (true) {
return;
}
- // First process all pending commands in the queue. During this processing
- // each message is checked to see if it is a plain break command. If there is
- // a plain break request in the queue or if the queue is empty a break event
- // is sent to the debugger.
- bool plain_break = false;
- if (command_queue_.IsEmpty()) {
- plain_break = true;
- } else {
- // Drain queue.
- while (!command_queue_.IsEmpty()) {
- command_received_->Wait();
- Logger::DebugTag("Get command from command_queue, in drain queue loop.");
- Vector<uint16_t> command = command_queue_.Get();
- // Support for sending a break command as just "break" instead of an
- // actual JSON break command.
- // If break is made into a separate API call, function
- // TwoByteEqualsASCII can be removed.
- if (TwoByteEqualsAscii(command, "break")) {
- plain_break = true;
- continue;
- }
-
- // Get the command as a string object.
- Handle<String> command_string;
- if (!command.is_empty()) {
- command_string = Factory::NewStringFromTwoByte(
- Vector<const uint16_t>(
- reinterpret_cast<const uint16_t*>(
- command.start()),
- command.length()));
- } else {
- command_string = Handle<String>();
- }
-
- // Process the request.
- Handle<String> message_string = Debugger::ProcessRequest(exec_state,
- command_string,
- false);
- // Convert text result to UTF-16 string and send it.
- v8::String::Value val(Utils::ToLocal(message_string));
- Vector<uint16_t> message(reinterpret_cast<uint16_t*>(*val),
- message_string->length());
- SendMessage(message);
-
- // Check whether one of the commands is a plain break request.
- if (!plain_break) {
- plain_break = Debugger::IsPlainBreakRequest(message_string);
- }
- }
- }
-
- // If this break event is not to go to the debugger just return.
- if (!plain_break) return;
-
// Notify the debugger that a debug event has occoured.
host_running_ = false;
SetEventJSONFromEvent(event_data);
Vector<uint16_t> command_copy = command.Clone();
Logger::DebugTag("Put command on command_queue.");
command_queue_.Put(command_copy);
- // If not in a break schedule a break and send the "request queued" response.
- if (host_running_) {
- v8::Debug::DebugBreak();
- uint16_t buffer[14] = {'r', 'e', 'q', 'u', 'e', 's', 't', ' ',
- 'q', 'u', 'e', 'u', 'e', 'd'};
- SendMessage(Vector<uint16_t>(buffer, 14));
- }
command_received_->Signal();
}
static Handle<String> ProcessRequest(Handle<Object> exec_state,
Handle<Object> request,
bool stopped);
- static bool IsPlainBreakRequest(Handle<Object> request);
-
static void OnDebugBreak(Handle<Object> break_points_hit);
static void OnException(Handle<Object> exception, bool uncaught);
static void OnBeforeCompile(Handle<Script> script);
static void MessageHandler(const uint16_t* message, int length, void *data) {
static char print_buffer[1000];
Utf16ToAscii(message, length, print_buffer);
- if (!strncmp(print_buffer, "request queued", 15)) {
- // Ignore "request queued" messages before blocking message queue,
- // by bumping semaphore to let them through.
- message_queue_barriers.semaphore_1->Signal();
- }
if (IsBreakEventMessage(print_buffer)) {
// Lets test script wait until break occurs to send commands.
// Signals when a break is reported.
CompileRun(source_1);
message_queue_barriers.barrier_1.Wait();
message_queue_barriers.barrier_2.Wait();
+ v8::Debug::DebugBreak();
CompileRun(source_2);
message_queue_barriers.barrier_3.Wait();
CompileRun(source_3);
void *data) {
static char print_buffer[1000];
Utf16ToAscii(message, length, print_buffer);
- if (!strncmp(print_buffer, "request queued", 15)) {
- return;
- }
if (IsBreakEventMessage(print_buffer)) {
threaded_debugging_barriers.barrier_2.Wait();
}
const int kBufSize = 1000;
uint16_t buffer[kBufSize];
- const char* command_1 = "{\"seq\":101,"
- "\"type\":\"request\","
- "\"command\":\"break\"}";
- const char* command_2 = "{\"seq\":102,"
+ const char* command_1 = "{\"seq\":102,"
"\"type\":\"request\","
"\"command\":\"evaluate\","
"\"arguments\":{\"expression\":\"bar(false)\"}}";
- const char* command_3 = "{\"seq\":103,"
+ const char* command_2 = "{\"seq\":103,"
"\"type\":\"request\","
"\"command\":\"continue\"}";
threaded_debugging_barriers.barrier_1.Wait();
- v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
+ v8::Debug::DebugBreak();
threaded_debugging_barriers.barrier_2.Wait();
+ v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
- v8::Debug::SendCommand(buffer, AsciiToUtf16(command_3, buffer));
}
DebuggerThread debugger_thread;
void *data) {
static char print_buffer[1000];
Utf16ToAscii(message, length, print_buffer);
- if (!strncmp(print_buffer, "request queued", 15)) {
- printf("%s\n", print_buffer);
- fflush(stdout);
- return;
- }
printf("%s\n", print_buffer);
fflush(stdout);
// v8 thread initializes, runs source_1
breakpoints_barriers->barrier_1.Wait();
// 1:Set breakpoint in cat().
+ v8::Debug::DebugBreak();
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
// 2:Set breakpoint in dog()
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));