| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2010-2011 Google Inc. All rights reserved. | 2 * Copyright (c) 2010-2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "bindings/core/v8/V8Debugger.h" | 32 #include "bindings/core/v8/V8Debugger.h" |
| 33 | 33 |
| 34 #include "bindings/core/v8/ScriptValue.h" | 34 #include "bindings/core/v8/ScriptValue.h" |
| 35 #include "bindings/core/v8/V8JavaScriptCallFrame.h" | 35 #include "bindings/core/v8/V8JavaScriptCallFrame.h" |
| 36 #include "bindings/core/v8/V8ScriptRunner.h" | 36 #include "bindings/core/v8/V8ScriptRunner.h" |
| 37 #include "core/inspector/JavaScriptCallFrame.h" | 37 #include "core/inspector/JavaScriptCallFrame.h" |
| 38 #include "core/inspector/ScriptDebugListener.h" | 38 #include "core/inspector/ScriptDebugListener.h" |
| 39 #include "platform/JSONValues.h" | 39 #include "platform/JSONValues.h" |
| 40 #include "wtf/Deque.h" | |
| 41 #include "wtf/StdLibExtras.h" | 40 #include "wtf/StdLibExtras.h" |
| 42 #include "wtf/ThreadingPrimitives.h" | |
| 43 #include "wtf/Vector.h" | 41 #include "wtf/Vector.h" |
| 44 #include "wtf/dtoa/utils.h" | 42 #include "wtf/dtoa/utils.h" |
| 45 #include "wtf/text/CString.h" | 43 #include "wtf/text/CString.h" |
| 46 | 44 |
| 47 namespace blink { | 45 namespace blink { |
| 48 | 46 |
| 49 namespace { | 47 namespace { |
| 50 const char stepIntoV8MethodName[] = "stepIntoStatement"; | 48 const char stepIntoV8MethodName[] = "stepIntoStatement"; |
| 51 const char stepOutV8MethodName[] = "stepOutOfFunction"; | 49 const char stepOutV8MethodName[] = "stepOutOfFunction"; |
| 52 } | 50 } |
| 53 | 51 |
| 54 class V8Debugger::ThreadSafeTaskQueue { | |
| 55 WTF_MAKE_NONCOPYABLE(ThreadSafeTaskQueue); | |
| 56 public: | |
| 57 ThreadSafeTaskQueue() { } | |
| 58 PassOwnPtr<Task> tryTake() | |
| 59 { | |
| 60 MutexLocker lock(m_mutex); | |
| 61 if (m_queue.isEmpty()) | |
| 62 return nullptr; | |
| 63 return m_queue.takeFirst(); | |
| 64 } | |
| 65 void append(PassOwnPtr<Task> task) | |
| 66 { | |
| 67 MutexLocker lock(m_mutex); | |
| 68 m_queue.append(task); | |
| 69 } | |
| 70 private: | |
| 71 Mutex m_mutex; | |
| 72 Deque<OwnPtr<Task>> m_queue; | |
| 73 }; | |
| 74 | |
| 75 v8::MaybeLocal<v8::Value> V8Debugger::callDebuggerMethod(const char* functionNam
e, int argc, v8::Local<v8::Value> argv[]) | 52 v8::MaybeLocal<v8::Value> V8Debugger::callDebuggerMethod(const char* functionNam
e, int argc, v8::Local<v8::Value> argv[]) |
| 76 { | 53 { |
| 77 v8::Local<v8::Object> debuggerScript = debuggerScriptLocal(); | 54 v8::Local<v8::Object> debuggerScript = debuggerScriptLocal(); |
| 78 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(debuggerScr
ipt->Get(v8InternalizedString(functionName))); | 55 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(debuggerScr
ipt->Get(v8InternalizedString(functionName))); |
| 79 ASSERT(m_isolate->InContext()); | 56 ASSERT(m_isolate->InContext()); |
| 80 return V8ScriptRunner::callInternalFunction(function, debuggerScript, argc,
argv, m_isolate); | 57 return V8ScriptRunner::callInternalFunction(function, debuggerScript, argc,
argv, m_isolate); |
| 81 } | 58 } |
| 82 | 59 |
| 83 V8Debugger::V8Debugger(v8::Isolate* isolate, Client* client) | 60 V8Debugger::V8Debugger(v8::Isolate* isolate, Client* client) |
| 84 : m_isolate(isolate) | 61 : m_isolate(isolate) |
| 85 , m_client(client) | 62 , m_client(client) |
| 86 , m_breakpointsActivated(true) | 63 , m_breakpointsActivated(true) |
| 87 , m_runningNestedMessageLoop(false) | 64 , m_runningNestedMessageLoop(false) |
| 88 , m_taskQueue(adoptPtr(new ThreadSafeTaskQueue)) | |
| 89 { | 65 { |
| 90 } | 66 } |
| 91 | 67 |
| 92 V8Debugger::~V8Debugger() | 68 V8Debugger::~V8Debugger() |
| 93 { | 69 { |
| 94 } | 70 } |
| 95 | 71 |
| 96 DEFINE_TRACE(V8Debugger) | 72 DEFINE_TRACE(V8Debugger) |
| 97 { | 73 { |
| 98 } | 74 } |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 } else { | 451 } else { |
| 476 v8::Local<v8::Value> argv[] = { m_executionState, v8::Integer::New(m_iso
late, index) }; | 452 v8::Local<v8::Value> argv[] = { m_executionState, v8::Integer::New(m_iso
late, index) }; |
| 477 currentCallFrameV8 = callDebuggerMethod("currentCallFrameByIndex", WTF_A
RRAY_LENGTH(argv), argv).ToLocalChecked(); | 453 currentCallFrameV8 = callDebuggerMethod("currentCallFrameByIndex", WTF_A
RRAY_LENGTH(argv), argv).ToLocalChecked(); |
| 478 } | 454 } |
| 479 ASSERT(!currentCallFrameV8.IsEmpty()); | 455 ASSERT(!currentCallFrameV8.IsEmpty()); |
| 480 if (!currentCallFrameV8->IsObject()) | 456 if (!currentCallFrameV8->IsObject()) |
| 481 return nullptr; | 457 return nullptr; |
| 482 return JavaScriptCallFrame::create(debuggerContext(), v8::Local<v8::Object>:
:Cast(currentCallFrameV8)); | 458 return JavaScriptCallFrame::create(debuggerContext(), v8::Local<v8::Object>:
:Cast(currentCallFrameV8)); |
| 483 } | 459 } |
| 484 | 460 |
| 485 void V8Debugger::interruptAndRun(PassOwnPtr<Task> task) | |
| 486 { | |
| 487 m_taskQueue->append(task); | |
| 488 m_isolate->RequestInterrupt(&v8InterruptCallback, this); | |
| 489 } | |
| 490 | |
| 491 void V8Debugger::runPendingTasks() | |
| 492 { | |
| 493 while (true) { | |
| 494 OwnPtr<Task> task = m_taskQueue->tryTake(); | |
| 495 if (!task) | |
| 496 return; | |
| 497 task->run(); | |
| 498 } | |
| 499 } | |
| 500 | |
| 501 static V8Debugger* toV8Debugger(v8::Local<v8::Value> data) | 461 static V8Debugger* toV8Debugger(v8::Local<v8::Value> data) |
| 502 { | 462 { |
| 503 void* p = v8::Local<v8::External>::Cast(data)->Value(); | 463 void* p = v8::Local<v8::External>::Cast(data)->Value(); |
| 504 return static_cast<V8Debugger*>(p); | 464 return static_cast<V8Debugger*>(p); |
| 505 } | 465 } |
| 506 | 466 |
| 507 void V8Debugger::breakProgramCallback(const v8::FunctionCallbackInfo<v8::Value>&
info) | 467 void V8Debugger::breakProgramCallback(const v8::FunctionCallbackInfo<v8::Value>&
info) |
| 508 { | 468 { |
| 509 ASSERT(2 == info.Length()); | 469 ASSERT(2 == info.Length()); |
| 510 V8Debugger* thisPtr = toV8Debugger(info.Data()); | 470 V8Debugger* thisPtr = toV8Debugger(info.Data()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 callDebuggerMethod("stepFrameStatement", 1, argv); | 510 callDebuggerMethod("stepFrameStatement", 1, argv); |
| 551 } else if (result == ScriptDebugListener::StepInto) { | 511 } else if (result == ScriptDebugListener::StepInto) { |
| 552 v8::Local<v8::Value> argv[] = { executionState }; | 512 v8::Local<v8::Value> argv[] = { executionState }; |
| 553 callDebuggerMethod(stepIntoV8MethodName, 1, argv); | 513 callDebuggerMethod(stepIntoV8MethodName, 1, argv); |
| 554 } else if (result == ScriptDebugListener::StepOut) { | 514 } else if (result == ScriptDebugListener::StepOut) { |
| 555 v8::Local<v8::Value> argv[] = { executionState }; | 515 v8::Local<v8::Value> argv[] = { executionState }; |
| 556 callDebuggerMethod(stepOutV8MethodName, 1, argv); | 516 callDebuggerMethod(stepOutV8MethodName, 1, argv); |
| 557 } | 517 } |
| 558 } | 518 } |
| 559 | 519 |
| 560 void V8Debugger::v8InterruptCallback(v8::Isolate*, void* data) | |
| 561 { | |
| 562 V8Debugger* server = static_cast<V8Debugger*>(data); | |
| 563 if (server->enabled()) | |
| 564 server->runPendingTasks(); | |
| 565 } | |
| 566 | |
| 567 void V8Debugger::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetail
s) | 520 void V8Debugger::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetail
s) |
| 568 { | 521 { |
| 569 V8Debugger* thisPtr = toV8Debugger(eventDetails.GetCallbackData()); | 522 V8Debugger* thisPtr = toV8Debugger(eventDetails.GetCallbackData()); |
| 570 thisPtr->handleV8DebugEvent(eventDetails); | 523 thisPtr->handleV8DebugEvent(eventDetails); |
| 571 } | 524 } |
| 572 | 525 |
| 573 v8::Local<v8::Value> V8Debugger::callInternalGetterFunction(v8::Local<v8::Object
> object, const char* functionName) | 526 v8::Local<v8::Value> V8Debugger::callInternalGetterFunction(v8::Local<v8::Object
> object, const char* functionName) |
| 574 { | 527 { |
| 575 v8::Local<v8::Value> getterValue = object->Get(v8InternalizedString(function
Name)); | 528 v8::Local<v8::Value> getterValue = object->Get(v8InternalizedString(function
Name)); |
| 576 ASSERT(!getterValue.IsEmpty() && getterValue->IsFunction()); | 529 ASSERT(!getterValue.IsEmpty() && getterValue->IsFunction()); |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 return callDebuggerMethod("setFunctionVariableValue", 4, argv); | 700 return callDebuggerMethod("setFunctionVariableValue", 4, argv); |
| 748 } | 701 } |
| 749 | 702 |
| 750 | 703 |
| 751 bool V8Debugger::isPaused() | 704 bool V8Debugger::isPaused() |
| 752 { | 705 { |
| 753 return m_pausedScriptState; | 706 return m_pausedScriptState; |
| 754 } | 707 } |
| 755 | 708 |
| 756 } // namespace blink | 709 } // namespace blink |
| OLD | NEW |