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 18 matching lines...) Expand all Loading... |
29 */ | 29 */ |
30 | 30 |
31 #include "config.h" | 31 #include "config.h" |
32 #include "core/inspector/V8Debugger.h" | 32 #include "core/inspector/V8Debugger.h" |
33 | 33 |
34 #include "bindings/core/v8/ScriptValue.h" | 34 #include "bindings/core/v8/ScriptValue.h" |
35 #include "bindings/core/v8/V8Binding.h" | 35 #include "bindings/core/v8/V8Binding.h" |
36 #include "bindings/core/v8/V8ScriptRunner.h" | 36 #include "bindings/core/v8/V8ScriptRunner.h" |
37 #include "bindings/core/v8/inspector/V8JavaScriptCallFrame.h" | 37 #include "bindings/core/v8/inspector/V8JavaScriptCallFrame.h" |
38 #include "core/inspector/JavaScriptCallFrame.h" | 38 #include "core/inspector/JavaScriptCallFrame.h" |
39 #include "core/inspector/ScriptDebugListener.h" | |
40 #include "platform/JSONValues.h" | 39 #include "platform/JSONValues.h" |
41 #include "wtf/StdLibExtras.h" | 40 #include "wtf/StdLibExtras.h" |
42 #include "wtf/Vector.h" | 41 #include "wtf/Vector.h" |
43 #include "wtf/dtoa/utils.h" | 42 #include "wtf/dtoa/utils.h" |
44 #include "wtf/text/CString.h" | 43 #include "wtf/text/CString.h" |
45 | 44 |
46 namespace blink { | 45 namespace blink { |
47 | 46 |
48 namespace { | 47 namespace { |
49 const char stepIntoV8MethodName[] = "stepIntoStatement"; | 48 const char stepIntoV8MethodName[] = "stepIntoStatement"; |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 v8::Local<v8::Array> hitBreakpoints; | 572 v8::Local<v8::Array> hitBreakpoints; |
574 thisPtr->handleProgramBreak(pausedScriptState, v8::Local<v8::Object>::Cast(i
nfo[0]), exception, hitBreakpoints); | 573 thisPtr->handleProgramBreak(pausedScriptState, v8::Local<v8::Object>::Cast(i
nfo[0]), exception, hitBreakpoints); |
575 } | 574 } |
576 | 575 |
577 void V8Debugger::handleProgramBreak(ScriptState* pausedScriptState, v8::Local<v8
::Object> executionState, v8::Local<v8::Value> exception, v8::Local<v8::Array> h
itBreakpointNumbers, bool isPromiseRejection) | 576 void V8Debugger::handleProgramBreak(ScriptState* pausedScriptState, v8::Local<v8
::Object> executionState, v8::Local<v8::Value> exception, v8::Local<v8::Array> h
itBreakpointNumbers, bool isPromiseRejection) |
578 { | 577 { |
579 // Don't allow nested breaks. | 578 // Don't allow nested breaks. |
580 if (m_runningNestedMessageLoop) | 579 if (m_runningNestedMessageLoop) |
581 return; | 580 return; |
582 | 581 |
583 ScriptDebugListener* listener = m_client->getDebugListenerForContext(pausedS
criptState->context()); | |
584 if (!listener) | |
585 return; | |
586 | |
587 Vector<String> breakpointIds; | 582 Vector<String> breakpointIds; |
588 if (!hitBreakpointNumbers.IsEmpty()) { | 583 if (!hitBreakpointNumbers.IsEmpty()) { |
589 breakpointIds.resize(hitBreakpointNumbers->Length()); | 584 breakpointIds.resize(hitBreakpointNumbers->Length()); |
590 for (size_t i = 0; i < hitBreakpointNumbers->Length(); i++) { | 585 for (size_t i = 0; i < hitBreakpointNumbers->Length(); i++) { |
591 v8::Local<v8::Value> hitBreakpointNumber = hitBreakpointNumbers->Get
(i); | 586 v8::Local<v8::Value> hitBreakpointNumber = hitBreakpointNumbers->Get
(i); |
592 ASSERT(!hitBreakpointNumber.IsEmpty() && hitBreakpointNumber->IsInt3
2()); | 587 ASSERT(!hitBreakpointNumber.IsEmpty() && hitBreakpointNumber->IsInt3
2()); |
593 breakpointIds[i] = String::number(hitBreakpointNumber->Int32Value())
; | 588 breakpointIds[i] = String::number(hitBreakpointNumber->Int32Value())
; |
594 } | 589 } |
595 } | 590 } |
596 | 591 |
597 m_pausedScriptState = pausedScriptState; | 592 m_pausedScriptState = pausedScriptState; |
598 m_executionState = executionState; | 593 m_executionState = executionState; |
599 SkipPauseRequest result = listener->didPause(pausedScriptState, currentCallF
rames(), ScriptValue(pausedScriptState, exception), breakpointIds, isPromiseReje
ction); | 594 SkipPauseRequest result = m_client->didPause(pausedScriptState, currentCallF
rames(), ScriptValue(pausedScriptState, exception), breakpointIds, isPromiseReje
ction); |
600 if (result == NoSkip) { | 595 if (result == NoSkip) { |
601 m_runningNestedMessageLoop = true; | 596 m_runningNestedMessageLoop = true; |
602 m_client->runMessageLoopOnPause(pausedScriptState->context()); | 597 m_client->runMessageLoopOnPause(pausedScriptState->context()); |
603 m_runningNestedMessageLoop = false; | 598 m_runningNestedMessageLoop = false; |
604 } | 599 } |
605 m_pausedScriptState.clear(); | 600 m_pausedScriptState.clear(); |
606 m_executionState.Clear(); | 601 m_executionState.Clear(); |
607 | 602 |
608 if (result == StepFrame) { | 603 if (result == StepFrame) { |
609 v8::Local<v8::Value> argv[] = { executionState }; | 604 v8::Local<v8::Value> argv[] = { executionState }; |
(...skipping 24 matching lines...) Expand all Loading... |
634 { | 629 { |
635 if (!enabled()) | 630 if (!enabled()) |
636 return; | 631 return; |
637 v8::DebugEvent event = eventDetails.GetEvent(); | 632 v8::DebugEvent event = eventDetails.GetEvent(); |
638 if (event != v8::AsyncTaskEvent && event != v8::Break && event != v8::Except
ion && event != v8::AfterCompile && event != v8::BeforeCompile && event != v8::C
ompileError && event != v8::PromiseEvent) | 633 if (event != v8::AsyncTaskEvent && event != v8::Break && event != v8::Except
ion && event != v8::AfterCompile && event != v8::BeforeCompile && event != v8::C
ompileError && event != v8::PromiseEvent) |
639 return; | 634 return; |
640 | 635 |
641 v8::Local<v8::Context> eventContext = eventDetails.GetEventContext(); | 636 v8::Local<v8::Context> eventContext = eventDetails.GetEventContext(); |
642 ASSERT(!eventContext.IsEmpty()); | 637 ASSERT(!eventContext.IsEmpty()); |
643 | 638 |
644 ScriptDebugListener* listener = m_client->getDebugListenerForContext(eventCo
ntext); | 639 v8::HandleScope scope(m_isolate); |
645 if (listener) { | 640 if (event == v8::AfterCompile || event == v8::CompileError) { |
646 v8::HandleScope scope(m_isolate); | 641 v8::Context::Scope contextScope(debuggerContext()); |
647 if (event == v8::AfterCompile || event == v8::CompileError) { | 642 v8::Local<v8::Value> argv[] = { eventDetails.GetEventData() }; |
648 v8::Context::Scope contextScope(debuggerContext()); | 643 v8::Local<v8::Value> value = callDebuggerMethod("getAfterCompileScript",
1, argv).ToLocalChecked(); |
649 v8::Local<v8::Value> argv[] = { eventDetails.GetEventData() }; | 644 ASSERT(value->IsObject()); |
650 v8::Local<v8::Value> value = callDebuggerMethod("getAfterCompileScri
pt", 1, argv).ToLocalChecked(); | 645 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); |
651 ASSERT(value->IsObject()); | 646 m_client->didParseSource(eventContext, createParsedScript(object, event
!= v8::AfterCompile ? CompileError : CompileSuccess)); |
652 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); | 647 } else if (event == v8::Exception) { |
653 listener->didParseSource(createParsedScript(object, event != v8::Aft
erCompile ? CompileError : CompileSuccess)); | 648 v8::Local<v8::Object> eventData = eventDetails.GetEventData(); |
654 } else if (event == v8::Exception) { | 649 v8::Local<v8::Value> exception = callInternalGetterFunction(eventData, "
exception"); |
655 v8::Local<v8::Object> eventData = eventDetails.GetEventData(); | 650 v8::Local<v8::Value> promise = callInternalGetterFunction(eventData, "pr
omise"); |
656 v8::Local<v8::Value> exception = callInternalGetterFunction(eventDat
a, "exception"); | 651 bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject(); |
657 v8::Local<v8::Value> promise = callInternalGetterFunction(eventData,
"promise"); | 652 handleProgramBreak(ScriptState::from(eventContext), eventDetails.GetExec
utionState(), exception, v8::Local<v8::Array>(), isPromiseRejection); |
658 bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject(); | 653 } else if (event == v8::Break) { |
659 handleProgramBreak(ScriptState::from(eventContext), eventDetails.Get
ExecutionState(), exception, v8::Local<v8::Array>(), isPromiseRejection); | 654 v8::Local<v8::Value> argv[] = { eventDetails.GetEventData() }; |
660 } else if (event == v8::Break) { | 655 v8::Local<v8::Value> hitBreakpoints = callDebuggerMethod("getBreakpointN
umbers", 1, argv).ToLocalChecked(); |
661 v8::Local<v8::Value> argv[] = { eventDetails.GetEventData() }; | 656 ASSERT(hitBreakpoints->IsArray()); |
662 v8::Local<v8::Value> hitBreakpoints = callDebuggerMethod("getBreakpo
intNumbers", 1, argv).ToLocalChecked(); | 657 handleProgramBreak(ScriptState::from(eventContext), eventDetails.GetExec
utionState(), v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>()); |
663 ASSERT(hitBreakpoints->IsArray()); | 658 } else if (event == v8::AsyncTaskEvent) { |
664 handleProgramBreak(ScriptState::from(eventContext), eventDetails.Get
ExecutionState(), v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>()); | 659 if (m_client->v8AsyncTaskEventsEnabled(ScriptState::from(eventContext))) |
665 } else if (event == v8::AsyncTaskEvent) { | 660 handleV8AsyncTaskEvent(ScriptState::from(eventContext), eventDetails
.GetExecutionState(), eventDetails.GetEventData()); |
666 if (listener->v8AsyncTaskEventsEnabled()) | 661 } else if (event == v8::PromiseEvent) { |
667 handleV8AsyncTaskEvent(listener, ScriptState::from(eventContext)
, eventDetails.GetExecutionState(), eventDetails.GetEventData()); | 662 if (m_client->v8PromiseEventsEnabled(ScriptState::from(eventContext))) |
668 } else if (event == v8::PromiseEvent) { | 663 handleV8PromiseEvent(ScriptState::from(eventContext), eventDetails.G
etExecutionState(), eventDetails.GetEventData()); |
669 if (listener->v8PromiseEventsEnabled()) | |
670 handleV8PromiseEvent(listener, ScriptState::from(eventContext),
eventDetails.GetExecutionState(), eventDetails.GetEventData()); | |
671 } | |
672 } | 664 } |
673 } | 665 } |
674 | 666 |
675 void V8Debugger::handleV8AsyncTaskEvent(ScriptDebugListener* listener, ScriptSta
te* pausedScriptState, v8::Local<v8::Object> executionState, v8::Local<v8::Objec
t> eventData) | 667 void V8Debugger::handleV8AsyncTaskEvent(ScriptState* pausedScriptState, v8::Loca
l<v8::Object> executionState, v8::Local<v8::Object> eventData) |
676 { | 668 { |
677 String type = toCoreStringWithUndefinedOrNullCheck(callInternalGetterFunctio
n(eventData, "type")); | 669 String type = toCoreStringWithUndefinedOrNullCheck(callInternalGetterFunctio
n(eventData, "type")); |
678 String name = toCoreStringWithUndefinedOrNullCheck(callInternalGetterFunctio
n(eventData, "name")); | 670 String name = toCoreStringWithUndefinedOrNullCheck(callInternalGetterFunctio
n(eventData, "name")); |
679 int id = callInternalGetterFunction(eventData, "id")->ToInteger(m_isolate)->
Value(); | 671 int id = callInternalGetterFunction(eventData, "id")->ToInteger(m_isolate)->
Value(); |
680 | 672 |
681 m_pausedScriptState = pausedScriptState; | 673 m_pausedScriptState = pausedScriptState; |
682 m_executionState = executionState; | 674 m_executionState = executionState; |
683 listener->didReceiveV8AsyncTaskEvent(pausedScriptState, type, name, id); | 675 m_client->didReceiveV8AsyncTaskEvent(pausedScriptState, type, name, id); |
684 m_pausedScriptState.clear(); | 676 m_pausedScriptState.clear(); |
685 m_executionState.Clear(); | 677 m_executionState.Clear(); |
686 } | 678 } |
687 | 679 |
688 void V8Debugger::handleV8PromiseEvent(ScriptDebugListener* listener, ScriptState
* pausedScriptState, v8::Local<v8::Object> executionState, v8::Local<v8::Object>
eventData) | 680 void V8Debugger::handleV8PromiseEvent(ScriptState* pausedScriptState, v8::Local<
v8::Object> executionState, v8::Local<v8::Object> eventData) |
689 { | 681 { |
690 v8::Local<v8::Value> argv[] = { eventData }; | 682 v8::Local<v8::Value> argv[] = { eventData }; |
691 v8::Local<v8::Value> value = callDebuggerMethod("getPromiseDetails", 1, argv
).ToLocalChecked(); | 683 v8::Local<v8::Value> value = callDebuggerMethod("getPromiseDetails", 1, argv
).ToLocalChecked(); |
692 ASSERT(value->IsObject()); | 684 ASSERT(value->IsObject()); |
693 v8::Local<v8::Object> promiseDetails = v8::Local<v8::Object>::Cast(value); | 685 v8::Local<v8::Object> promiseDetails = v8::Local<v8::Object>::Cast(value); |
694 v8::Local<v8::Object> promise = promiseDetails->Get(v8InternalizedString("pr
omise"))->ToObject(m_isolate); | 686 v8::Local<v8::Object> promise = promiseDetails->Get(v8InternalizedString("pr
omise"))->ToObject(m_isolate); |
695 int status = promiseDetails->Get(v8InternalizedString("status"))->ToInteger(
m_isolate)->Value(); | 687 int status = promiseDetails->Get(v8InternalizedString("status"))->ToInteger(
m_isolate)->Value(); |
696 v8::Local<v8::Value> parentPromise = promiseDetails->Get(v8InternalizedStrin
g("parentPromise")); | 688 v8::Local<v8::Value> parentPromise = promiseDetails->Get(v8InternalizedStrin
g("parentPromise")); |
697 | 689 |
698 m_pausedScriptState = pausedScriptState; | 690 m_pausedScriptState = pausedScriptState; |
699 m_executionState = executionState; | 691 m_executionState = executionState; |
700 listener->didReceiveV8PromiseEvent(pausedScriptState, promise, parentPromise
, status); | 692 m_client->didReceiveV8PromiseEvent(pausedScriptState, promise, parentPromise
, status); |
701 m_pausedScriptState.clear(); | 693 m_pausedScriptState.clear(); |
702 m_executionState.Clear(); | 694 m_executionState.Clear(); |
703 } | 695 } |
704 | 696 |
705 V8Debugger::ParsedScript V8Debugger::createParsedScript(v8::Local<v8::Object> ob
ject, CompileResult compileResult) | 697 V8Debugger::ParsedScript V8Debugger::createParsedScript(v8::Local<v8::Object> ob
ject, CompileResult compileResult) |
706 { | 698 { |
707 v8::Local<v8::Value> id = object->Get(v8InternalizedString("id")); | 699 v8::Local<v8::Value> id = object->Get(v8InternalizedString("id")); |
708 ASSERT(!id.IsEmpty() && id->IsInt32()); | 700 ASSERT(!id.IsEmpty() && id->IsInt32()); |
709 | 701 |
710 ParsedScript parsedScript; | 702 ParsedScript parsedScript; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 return callDebuggerMethod("setFunctionVariableValue", 4, argv); | 792 return callDebuggerMethod("setFunctionVariableValue", 4, argv); |
801 } | 793 } |
802 | 794 |
803 | 795 |
804 bool V8Debugger::isPaused() | 796 bool V8Debugger::isPaused() |
805 { | 797 { |
806 return m_pausedScriptState; | 798 return m_pausedScriptState; |
807 } | 799 } |
808 | 800 |
809 } // namespace blink | 801 } // namespace blink |
OLD | NEW |