| /* |
| * Copyright 2015 Google Inc. All Rights Reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #ifndef COBALT_SCRIPT_JAVASCRIPTCORE_JSC_DEBUGGER_H_ |
| #define COBALT_SCRIPT_JAVASCRIPTCORE_JSC_DEBUGGER_H_ |
| |
| #include <string> |
| #include <vector> |
| |
| #include "base/compiler_specific.h" |
| #include "base/threading/thread_checker.h" |
| #include "cobalt/script/javascriptcore/jsc_global_environment.h" |
| #include "cobalt/script/script_debugger.h" |
| #include "cobalt/script/source_provider.h" |
| |
| #include "third_party/WebKit/Source/JavaScriptCore/config.h" |
| #include "third_party/WebKit/Source/JavaScriptCore/debugger/Debugger.h" |
| #include "third_party/WebKit/Source/JavaScriptCore/debugger/DebuggerCallFrame.h" |
| #include "third_party/WebKit/Source/WTF/wtf/HashSet.h" |
| #include "third_party/WebKit/Source/WTF/wtf/text/WTFString.h" |
| |
| namespace JSC { |
| class ExecState; |
| class JSGlobalData; |
| class JSGlobalObject; |
| class JSScope; |
| class JSValue; |
| class SourceProvider; |
| } |
| |
| namespace cobalt { |
| namespace script { |
| namespace javascriptcore { |
| |
| // JavaScriptCore-specific implementation of a JavaScript debugger. |
| // Uses multiple inheritance in accordance with the C++ style guide to extend |
| // JSC::Debugger and implement ScriptDebugger. |
| // |
| // Only the ScriptDebugger is publicly exposed. |
| // This class is not designed to be thread-safe - it is assumed that all |
| // public methods will be run on the same message loop as the JavaScript |
| // global object to which this debugger connects. |
| class JSCDebugger : protected JSC::Debugger, public ScriptDebugger { |
| public: |
| JSCDebugger(GlobalEnvironment* global_environment, Delegate* delegate); |
| ~JSCDebugger() OVERRIDE; |
| |
| // Implementation of ScriptDebugger. |
| void Attach() OVERRIDE; |
| void Detach() OVERRIDE; |
| void Pause() OVERRIDE; |
| void Resume() OVERRIDE; |
| void SetBreakpoint(const std::string& script_id, int line_number, |
| int column_number) OVERRIDE; |
| PauseOnExceptionsState SetPauseOnExceptions( |
| PauseOnExceptionsState state) OVERRIDE; |
| void StepInto() OVERRIDE; |
| void StepOut() OVERRIDE; |
| void StepOver() OVERRIDE; |
| |
| protected: |
| // Hides a non-virtual JSC::Debugger method with the same name. |
| void attach(JSC::JSGlobalObject* global_object); |
| |
| // The following methods are overrides of pure virtual methods in |
| // JSC::Debugger, hence the non-standard names. |
| void detach(JSC::JSGlobalObject* global_object) OVERRIDE; |
| |
| void sourceParsed(JSC::ExecState* exec_state, |
| JSC::SourceProvider* source_provider, int error_line, |
| const WTF::String& error_message) OVERRIDE; |
| |
| void exception(const JSC::DebuggerCallFrame& call_frame, intptr_t source_id, |
| int line_number, int column_number, bool has_handler) OVERRIDE; |
| |
| void atStatement(const JSC::DebuggerCallFrame& call_frame, intptr_t source_id, |
| int line_number, int column_number) OVERRIDE; |
| |
| void callEvent(const JSC::DebuggerCallFrame& call_frame, intptr_t source_id, |
| int line_number, int column_number) OVERRIDE; |
| |
| void returnEvent(const JSC::DebuggerCallFrame& call_frame, intptr_t source_id, |
| int line_number, int column_number) OVERRIDE; |
| |
| void willExecuteProgram(const JSC::DebuggerCallFrame& call_frame, |
| intptr_t source_id, int line_number, |
| int column_number) OVERRIDE; |
| |
| void didExecuteProgram(const JSC::DebuggerCallFrame& call_frame, |
| intptr_t source_id, int line_number, |
| int column_number) OVERRIDE; |
| |
| void didReachBreakpoint(const JSC::DebuggerCallFrame& call_frame, |
| intptr_t source_id, int line_number, |
| int column_number) OVERRIDE; |
| |
| private: |
| // Physical breakpoint corresponding to a specific source location. |
| // TODO: Include other attributes, e.g. condition. |
| struct Breakpoint { |
| Breakpoint(intptr_t source_id, int line_number, int column_number) |
| : source_id(source_id), |
| line_number(line_number), |
| column_number(column_number) {} |
| intptr_t source_id; |
| int line_number; |
| int column_number; |
| }; |
| |
| typedef std::vector<Breakpoint> BreakpointVector; |
| |
| // Sets the |is_paused_| member of the debugger while in scope, unsets it |
| // on destruction. |
| class ScopedPausedState { |
| public: |
| explicit ScopedPausedState(JSCDebugger* debugger) : debugger(debugger) { |
| debugger->is_paused_ = true; |
| } |
| ~ScopedPausedState() { debugger->is_paused_ = false; } |
| |
| private: |
| JSCDebugger* debugger; |
| }; |
| |
| // Convenience function to get the global object pointer from the proxy. |
| JSCGlobalObject* GetGlobalObject() const; |
| |
| // Update functions called by the overridden methods from JSC:Debugger above |
| // (e.g. |atStatement|) as script is executed. |
| void UpdateAndPauseIfNeeded(const JSC::DebuggerCallFrame& call_frame, |
| intptr_t source_id, int line_number, |
| int column_number); |
| void UpdateSourceLocation(intptr_t source_id, int line_number, |
| int column_number); |
| void UpdateCallFrame(const JSC::DebuggerCallFrame& call_frame); |
| void PauseIfNeeded(const JSC::DebuggerCallFrame& call_frame); |
| |
| // Sends event notifications via |delegate_|. |
| void SendPausedEvent(const JSC::DebuggerCallFrame& call_frame); |
| void SendResumedEvent(); |
| |
| // Whether any of the currently active breakpoints matches the current |
| // source location. |
| bool IsBreakpointAtCurrentLocation() const; |
| |
| base::ThreadChecker thread_checker_; |
| GlobalEnvironment* global_environment_; |
| |
| // Lifetime managed by the caller of this object's constructor. |
| Delegate* delegate_; |
| |
| // Whether script execution pauses on exceptions. |
| PauseOnExceptionsState pause_on_exceptions_; |
| |
| // Code execution control flags. Script execution can pause on the next |
| // statement, or on a specific call frame. |
| bool pause_on_next_statement_; |
| JSC::CallFrame* pause_on_call_frame_; |
| |
| // Current call frame. |
| JSC::DebuggerCallFrame current_call_frame_; |
| |
| // Current source location. |
| intptr_t current_source_id_; |
| int current_line_number_; |
| int current_column_number_; |
| |
| // Whether script execution is currently paused. |
| bool is_paused_; |
| |
| // Currently active breakpoints. |
| BreakpointVector breakpoints_; |
| }; |
| |
| } // namespace javascriptcore |
| } // namespace script |
| } // namespace cobalt |
| |
| #endif // COBALT_SCRIPT_JAVASCRIPTCORE_JSC_DEBUGGER_H_ |