Changeset 158937 in webkit


Ignore:
Timestamp:
Nov 8, 2013 12:03:50 PM (10 years ago)
Author:
mark.lam@apple.com
Message:

Move breakpoint (and exception break) functionality into JSC::Debugger.
https://bugs.webkit.org/show_bug.cgi?id=121796.

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

  • In ScriptDebugServer and JSC::Debugger, SourceID and BreakpointID are now numeric tokens.
  • JSC::Debugger now tracks user defined breakpoints in a JSC::Breakpoint record. Previously, this info is tracked in the ScriptBreakpoint record in ScriptDebugServer. The only element of ScriptBreakpoint that is not being tracked by JSC::Breakpoint is the ScriptBreakpointAction.

The ScriptBreakpointAction is still tracked by the ScriptDebugServer

in a list keyed on the corresponding BreakpointID.

The ScriptBreakpoint record is now only used as a means of passing

breakpoint paramaters to the ScriptDebugServer.

  • ScriptDebugServer now no longer accesses the JSC::CallFrame* directly. It always goes through the DebuggerCallFrame.

(JSC::Breakpoint::Breakpoint):

  • Breakpoint class to track info for each breakpoint in JSC::Debugger.
  • debugger/Debugger.cpp:

(JSC::DebuggerCallFrameScope::DebuggerCallFrameScope):
(JSC::DebuggerCallFrameScope::~DebuggerCallFrameScope):
(JSC::Debugger::Debugger):
(JSC::Debugger::detach):
(JSC::Debugger::updateNeedForOpDebugCallbacks):
(JSC::Debugger::setBreakpoint):
(JSC::Debugger::removeBreakpoint):
(JSC::Debugger::hasBreakpoint):
(JSC::Debugger::clearBreakpoints):
(JSC::Debugger::setBreakpointsActivated):
(JSC::Debugger::setPauseOnExceptionsState):
(JSC::Debugger::setPauseOnNextStatement):
(JSC::Debugger::breakProgram):
(JSC::Debugger::continueProgram):
(JSC::Debugger::stepIntoStatement):
(JSC::Debugger::stepOverStatement):
(JSC::Debugger::stepOutOfFunction):
(JSC::Debugger::updateCallFrame):
(JSC::Debugger::updateCallFrameAndPauseIfNeeded):
(JSC::Debugger::pauseIfNeeded):
(JSC::Debugger::exception):
(JSC::Debugger::atStatement):
(JSC::Debugger::callEvent):
(JSC::Debugger::returnEvent):
(JSC::Debugger::willExecuteProgram):
(JSC::Debugger::didExecuteProgram):
(JSC::Debugger::didReachBreakpoint):
(JSC::Debugger::currentDebuggerCallFrame):

  • debugger/Debugger.h:
  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::sourceID):
(JSC::DebuggerCallFrame::sourceIDForCallFrame):

  • debugger/DebuggerCallFrame.h:
  • debugger/DebuggerPrimitives.h: Added.
  • define SourceID, noSourceID, BreakpointID, and noBreakpointID.

Source/WebCore:

No new tests.

  • In ScriptDebugServer and JSC::Debugger, SourceID and BreakpointID are now numeric tokens.
  • JSC::Debugger now tracks user defined breakpoints in a JSC::Breakpoint record. Previously, this info is tracked in the ScriptBreakpoint record in ScriptDebugServer. The only element of ScriptBreakpoint that is not being tracked by JSC::Breakpoint is the ScriptBreakpointAction.

The ScriptBreakpointAction is still tracked by the ScriptDebugServer

in a list keyed on the corresponding BreakpointID.

The ScriptBreakpoint record is now only used as a means of passing

breakpoint paramaters to the ScriptDebugServer.

  • ScriptDebugServer now no longer accesses the JSC::CallFrame* directly. It always goes through the DebuggerCallFrame.
  • GNUmakefile.list.am:
  • WebCore.vcxproj/WebCore.vcxproj:
  • WebCore.vcxproj/WebCore.vcxproj.filters:
  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/BreakpointID.h: Added.
  • bindings/js/ScriptDebugServer.cpp:

(WebCore::ScriptDebugServer::ScriptDebugServer):
(WebCore::ScriptDebugServer::setBreakpoint):
(WebCore::ScriptDebugServer::removeBreakpoint):
(WebCore::ScriptDebugServer::clearBreakpoints):
(WebCore::ScriptDebugServer::dispatchDidPause):
(WebCore::ScriptDebugServer::dispatchDidContinue):
(WebCore::ScriptDebugServer::dispatchDidParseSource):
(WebCore::ScriptDebugServer::notifyDoneProcessingDebuggerEvents):
(WebCore::ScriptDebugServer::needPauseHandling):
(WebCore::ScriptDebugServer::handleBreakpointHit):
(WebCore::ScriptDebugServer::handleExceptionInBreakpointCondition):
(WebCore::ScriptDebugServer::handlePause):

  • bindings/js/ScriptDebugServer.h:
  • bindings/js/SourceID.h: Added.
  • bindings/js/WorkerScriptDebugServer.cpp:

(WebCore::WorkerScriptDebugServer::WorkerScriptDebugServer):

  • bindings/js/WorkerScriptDebugServer.h:
  • inspector/InspectorDebuggerAgent.cpp:

(WebCore::InspectorDebuggerAgent::InspectorDebuggerAgent):
(WebCore::parseLocation):
(WebCore::InspectorDebuggerAgent::setBreakpoint):
(WebCore::InspectorDebuggerAgent::continueToLocation):
(WebCore::InspectorDebuggerAgent::resolveBreakpoint):
(WebCore::InspectorDebuggerAgent::searchInContent):
(WebCore::InspectorDebuggerAgent::getScriptSource):
(WebCore::InspectorDebuggerAgent::didParseSource):
(WebCore::InspectorDebuggerAgent::didPause):
(WebCore::InspectorDebuggerAgent::clear):

  • inspector/InspectorDebuggerAgent.h:
  • inspector/ScriptDebugListener.h:

Source/WebKit/mac:

  • WebView/WebScriptDebugger.h:
  • WebView/WebScriptDebugger.mm:

(WebScriptDebugger::WebScriptDebugger):
(WebScriptDebugger::handlePause):

Location:
trunk/Source
Files:
4 added
24 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r158929 r158937  
     12013-11-08  Mark Lam  <mark.lam@apple.com>
     2
     3        Move breakpoint (and exception break) functionality into JSC::Debugger.
     4        https://bugs.webkit.org/show_bug.cgi?id=121796.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        - In ScriptDebugServer and JSC::Debugger, SourceID and BreakpointID are
     9          now numeric tokens.
     10
     11        - JSC::Debugger now tracks user defined breakpoints in a JSC::Breakpoint
     12          record. Previously, this info is tracked in the ScriptBreakpoint record
     13          in ScriptDebugServer. The only element of ScriptBreakpoint that is not
     14          being tracked by JSC::Breakpoint is the ScriptBreakpointAction.
     15             The ScriptBreakpointAction is still tracked by the ScriptDebugServer
     16          in a list keyed on the corresponding BreakpointID.
     17             The ScriptBreakpoint record is now only used as a means of passing
     18          breakpoint paramaters to the ScriptDebugServer.
     19
     20        - ScriptDebugServer now no longer accesses the JSC::CallFrame* directly.
     21          It always goes through the DebuggerCallFrame.
     22
     23        * GNUmakefile.list.am:
     24        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     25        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     26        * JavaScriptCore.xcodeproj/project.pbxproj:
     27        * debugger/Breakpoint.h: Added.
     28        (JSC::Breakpoint::Breakpoint):
     29        - Breakpoint class to track info for each breakpoint in JSC::Debugger.
     30        * debugger/Debugger.cpp:
     31        (JSC::DebuggerCallFrameScope::DebuggerCallFrameScope):
     32        (JSC::DebuggerCallFrameScope::~DebuggerCallFrameScope):
     33        (JSC::Debugger::Debugger):
     34        (JSC::Debugger::detach):
     35        (JSC::Debugger::updateNeedForOpDebugCallbacks):
     36        (JSC::Debugger::setBreakpoint):
     37        (JSC::Debugger::removeBreakpoint):
     38        (JSC::Debugger::hasBreakpoint):
     39        (JSC::Debugger::clearBreakpoints):
     40        (JSC::Debugger::setBreakpointsActivated):
     41        (JSC::Debugger::setPauseOnExceptionsState):
     42        (JSC::Debugger::setPauseOnNextStatement):
     43        (JSC::Debugger::breakProgram):
     44        (JSC::Debugger::continueProgram):
     45        (JSC::Debugger::stepIntoStatement):
     46        (JSC::Debugger::stepOverStatement):
     47        (JSC::Debugger::stepOutOfFunction):
     48        (JSC::Debugger::updateCallFrame):
     49        (JSC::Debugger::updateCallFrameAndPauseIfNeeded):
     50        (JSC::Debugger::pauseIfNeeded):
     51        (JSC::Debugger::exception):
     52        (JSC::Debugger::atStatement):
     53        (JSC::Debugger::callEvent):
     54        (JSC::Debugger::returnEvent):
     55        (JSC::Debugger::willExecuteProgram):
     56        (JSC::Debugger::didExecuteProgram):
     57        (JSC::Debugger::didReachBreakpoint):
     58        (JSC::Debugger::currentDebuggerCallFrame):
     59        * debugger/Debugger.h:
     60        * debugger/DebuggerCallFrame.cpp:
     61        (JSC::DebuggerCallFrame::sourceID):
     62        (JSC::DebuggerCallFrame::sourceIDForCallFrame):
     63        * debugger/DebuggerCallFrame.h:
     64        * debugger/DebuggerPrimitives.h: Added.
     65        - define SourceID, noSourceID, BreakpointID, and noBreakpointID.
     66
    1672013-11-08  Oliver Hunt  <oliver@apple.com>
    268
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r158793 r158937  
    562562        Source/JavaScriptCore/heap/WriteBarrierSupport.h \
    563563        Source/JavaScriptCore/config.h \
     564        Source/JavaScriptCore/debugger/Breakpoint.h \
    564565        Source/JavaScriptCore/debugger/DebuggerActivation.cpp \
    565566        Source/JavaScriptCore/debugger/DebuggerActivation.h \
     
    568569        Source/JavaScriptCore/debugger/Debugger.cpp \
    569570        Source/JavaScriptCore/debugger/Debugger.h \
     571        Source/JavaScriptCore/debugger/DebuggerPrimitives.h \
    570572        Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APICast.h \
    571573        Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APIShims.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r158793 r158937  
    786786    <ClInclude Include="..\bytecompiler\RegisterID.h" />
    787787    <ClInclude Include="..\config.h" />
     788    <ClInclude Include="..\debugger\Breakpoint.h" />
    788789    <ClInclude Include="..\debugger\Debugger.h" />
    789790    <ClInclude Include="..\debugger\DebuggerActivation.h" />
    790791    <ClInclude Include="..\debugger\DebuggerCallFrame.h" />
     792    <ClInclude Include="..\debugger\DebuggerPrimitives.h" />
    791793    <ClInclude Include="..\dfg\DFGAbstractHeap.h" />
    792794    <ClInclude Include="..\dfg\DFGAbstractInterpreter.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r158793 r158937  
    14701470      <Filter>bytecodecompiler</Filter>
    14711471    </ClInclude>
     1472    <ClInclude Include="..\debugger\Breakpoint.h">
     1473      <Filter>debugger</Filter>
     1474    </ClInclude>
    14721475    <ClInclude Include="..\debugger\Debugger.h">
    14731476      <Filter>debugger</Filter>
     
    14771480    </ClInclude>
    14781481    <ClInclude Include="..\debugger\DebuggerCallFrame.h">
     1482      <Filter>debugger</Filter>
     1483    </ClInclude>
     1484    <ClInclude Include="..\debugger\DebuggerPrimitives.h">
    14791485      <Filter>debugger</Filter>
    14801486    </ClInclude>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r158793 r158937  
    12211221                FE4A332015BD2E07006F54F3 /* VMInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4A331E15BD2E07006F54F3 /* VMInspector.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12221222                FE6617281774E03500495B00 /* VMStackBounds.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6617271774E03500495B00 /* VMStackBounds.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1223                FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861E182B7A0400F6D851 /* Breakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1224                FEA08621182B7A0400F6D851 /* DebuggerPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12231225                FED287B215EC9A5700DA8161 /* LLIntOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = FED287B115EC9A5700DA8161 /* LLIntOpcode.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12241226                FED94F2E171E3E2300BE77A4 /* Watchdog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */; };
     
    25302532                FE4A331E15BD2E07006F54F3 /* VMInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMInspector.h; sourceTree = "<group>"; };
    25312533                FE6617271774E03500495B00 /* VMStackBounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMStackBounds.h; sourceTree = "<group>"; };
     2534                FEA0861E182B7A0400F6D851 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpoint.h; sourceTree = "<group>"; };
     2535                FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerPrimitives.h; sourceTree = "<group>"; };
    25322536                FED287B115EC9A5700DA8161 /* LLIntOpcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntOpcode.h; path = llint/LLIntOpcode.h; sourceTree = "<group>"; };
    25332537                FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Watchdog.cpp; sourceTree = "<group>"; };
     
    31613165                        isa = PBXGroup;
    31623166                        children = (
     3167                                FEA0861E182B7A0400F6D851 /* Breakpoint.h */,
     3168                                FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */,
    31633169                                F692A8580255597D01FF60F7 /* Debugger.cpp */,
    31643170                                F692A8590255597D01FF60F7 /* Debugger.h */,
     
    41204126                                65C0285D1717966800351E35 /* ARMv7DOpcode.h in Headers */,
    41214127                                0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */,
     4128                                FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */,
    41224129                                A7A8AF3517ADB5F3005AB174 /* ArrayBuffer.h in Headers */,
     4130                                FEA08621182B7A0400F6D851 /* DebuggerPrimitives.h in Headers */,
    41234131                                A7A8AF3717ADB5F3005AB174 /* ArrayBufferView.h in Headers */,
    41244132                                BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */,
  • trunk/Source/JavaScriptCore/debugger/Debugger.cpp

    r157746 r158937  
    11/*
    2  *  Copyright (C) 2008 Apple Inc. All rights reserved.
     2 *  Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
    33 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
    44 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
     
    2323#include "Debugger.h"
    2424
     25#include "DebuggerCallFrame.h"
    2526#include "Error.h"
    2627#include "HeapIterationScope.h"
    2728#include "Interpreter.h"
     29#include "JSCJSValueInlines.h"
    2830#include "JSFunction.h"
    2931#include "JSGlobalObject.h"
     
    9294namespace JSC {
    9395
    94 Debugger::Debugger()
    95     : m_needsExceptionCallbacks(false)
     96class DebuggerCallFrameScope {
     97public:
     98    DebuggerCallFrameScope(Debugger& debugger)
     99        : m_debugger(debugger)
     100    {
     101        ASSERT(!m_debugger.m_currentDebuggerCallFrame);
     102        if (m_debugger.m_currentCallFrame)
     103            m_debugger.m_currentDebuggerCallFrame = DebuggerCallFrame::create(debugger.m_currentCallFrame);
     104    }
     105
     106    ~DebuggerCallFrameScope()
     107    {
     108        if (m_debugger.m_currentDebuggerCallFrame) {
     109            m_debugger.m_currentDebuggerCallFrame->invalidate();
     110            m_debugger.m_currentDebuggerCallFrame = 0;
     111        }
     112    }
     113
     114private:
     115    Debugger& m_debugger;
     116};
     117
     118
     119Debugger::Debugger(bool isInWorkerThread)
     120    : m_pauseOnExceptionsState(DontPauseOnExceptions)
     121    , m_pauseOnNextStatement(false)
     122    , m_isPaused(false)
     123    , m_breakpointsActivated(true)
     124    , m_hasHandlerForExceptionCallback(false)
     125    , m_isInWorkerThread(isInWorkerThread)
     126    , m_reasonForPause(NotPaused)
     127    , m_pauseOnCallFrame(0)
     128    , m_currentCallFrame(0)
     129    , m_lastExecutedLine(UINT_MAX)
     130    , m_lastExecutedSourceID(noSourceID)
     131    , m_topBreakpointID(noBreakpointID)
    96132    , m_needsOpDebugCallbacks(false)
    97133    , m_shouldPause(false)
    98     , m_numberOfBreakpoints(0)
    99134{
    100135}
     
    116151void Debugger::detach(JSGlobalObject* globalObject)
    117152{
     153    // If we're detaching from the currently executing global object, manually tear down our
     154    // stack, since we won't get further debugger callbacks to do so. Also, resume execution,
     155    // since there's no point in staying paused once a window closes.
     156    if (m_currentCallFrame && m_currentCallFrame->dynamicGlobalObject() == globalObject) {
     157        m_currentCallFrame = 0;
     158        m_pauseOnCallFrame = 0;
     159        continueProgram();
     160    }
     161
    118162    ASSERT(m_globalObjects.contains(globalObject));
    119163    m_globalObjects.remove(globalObject);
    120164    globalObject->setDebugger(0);
    121 }
    122 
    123 void Debugger::setNeedsExceptionCallbacks(bool value)
    124 {
    125     m_needsExceptionCallbacks = value;
    126165}
    127166
     
    147186}
    148187
    149 void Debugger::updateNumberOfBreakpoints(int numberOfBreakpoints)
    150 {
    151     ASSERT(numberOfBreakpoints >= 0);
    152     m_numberOfBreakpoints = numberOfBreakpoints;
     188void Debugger::updateNeedForOpDebugCallbacks()
     189{
     190    size_t numberOfBreakpoints = m_breakpointIDToBreakpoint.size();
     191    m_needsOpDebugCallbacks = m_shouldPause || numberOfBreakpoints;
     192}
     193
     194BreakpointID Debugger::setBreakpoint(Breakpoint breakpoint, unsigned& actualLine, unsigned& actualColumn)
     195{
     196    SourceID sourceID = breakpoint.sourceID;
     197    unsigned line = breakpoint.line;
     198    unsigned column = breakpoint.column;
     199
     200    SourceIDToBreakpointsMap::iterator it = m_sourceIDToBreakpoints.find(sourceID);
     201    if (it == m_sourceIDToBreakpoints.end())
     202        it = m_sourceIDToBreakpoints.set(sourceID, LineToBreakpointsMap()).iterator;
     203    LineToBreakpointsMap::iterator breaksIt = it->value.find(line);
     204    if (breaksIt == it->value.end())
     205        breaksIt = it->value.set(line, BreakpointsInLine()).iterator;
     206
     207    BreakpointsInLine& breakpoints = breaksIt->value;
     208    unsigned breakpointsCount = breakpoints.size();
     209    for (unsigned i = 0; i < breakpointsCount; i++)
     210        if (breakpoints[i].column == column) {
     211            // The breakpoint already exists. We're not allowed to create a new
     212            // breakpoint at this location. Rather than returning the breakpointID
     213            // of the pre-existing breakpoint, we need to return noBreakpointID
     214            // to indicate that we're not creating a new one.
     215            return noBreakpointID;
     216        }
     217
     218    BreakpointID id = ++m_topBreakpointID;
     219    RELEASE_ASSERT(id != noBreakpointID);
     220
     221    breakpoint.id = id;
     222    actualLine = line;
     223    actualColumn = column;
     224
     225    breakpoints.append(breakpoint);
     226    m_breakpointIDToBreakpoint.set(id, &breakpoints.last());
     227
    153228    updateNeedForOpDebugCallbacks();
    154 }
    155 
    156 void Debugger::updateNeedForOpDebugCallbacks()
    157 {
    158     m_needsOpDebugCallbacks = m_shouldPause || m_numberOfBreakpoints;
     229
     230    return id;
     231}
     232
     233void Debugger::removeBreakpoint(BreakpointID id)
     234{
     235    ASSERT(id != noBreakpointID);
     236
     237    BreakpointIDToBreakpointMap::iterator idIt = m_breakpointIDToBreakpoint.find(id);
     238    ASSERT(idIt != m_breakpointIDToBreakpoint.end());
     239    Breakpoint& breakpoint = *idIt->value;
     240
     241    SourceID sourceID = breakpoint.sourceID;
     242    ASSERT(sourceID);
     243    SourceIDToBreakpointsMap::iterator it = m_sourceIDToBreakpoints.find(sourceID);
     244    ASSERT(it != m_sourceIDToBreakpoints.end());
     245    LineToBreakpointsMap::iterator breaksIt = it->value.find(breakpoint.line);
     246    ASSERT(breaksIt != it->value.end());
     247
     248    BreakpointsInLine& breakpoints = breaksIt->value;
     249    unsigned breakpointsCount = breakpoints.size();
     250    for (unsigned i = 0; i < breakpointsCount; i++) {
     251        if (breakpoints[i].id == breakpoint.id) {
     252            breakpoints.remove(i);
     253            m_breakpointIDToBreakpoint.remove(idIt);
     254
     255            if (breakpoints.isEmpty()) {
     256                it->value.remove(breaksIt);
     257                if (it->value.isEmpty())
     258                    m_sourceIDToBreakpoints.remove(it);
     259            }
     260            break;
     261        }
     262    }
     263
     264    updateNeedForOpDebugCallbacks();
     265}
     266
     267bool Debugger::hasBreakpoint(SourceID sourceID, const TextPosition& position, Breakpoint *hitBreakpoint) const
     268{
     269    if (!m_breakpointsActivated)
     270        return false;
     271
     272    SourceIDToBreakpointsMap::const_iterator it = m_sourceIDToBreakpoints.find(sourceID);
     273    if (it == m_sourceIDToBreakpoints.end())
     274        return false;
     275
     276    unsigned line = position.m_line.zeroBasedInt();
     277    unsigned column = position.m_column.zeroBasedInt();
     278
     279    LineToBreakpointsMap::const_iterator breaksIt = it->value.find(line);
     280    if (breaksIt == it->value.end())
     281        return false;
     282
     283    bool hit = false;
     284    const BreakpointsInLine& breakpoints = breaksIt->value;
     285    unsigned breakpointsCount = breakpoints.size();
     286    unsigned i;
     287    for (i = 0; i < breakpointsCount; i++) {
     288        unsigned breakLine = breakpoints[i].line;
     289        unsigned breakColumn = breakpoints[i].column;
     290        // Since frontend truncates the indent, the first statement in a line must match the breakpoint (line,0).
     291        if ((line != m_lastExecutedLine && line == breakLine && !breakColumn)
     292            || (line == breakLine && column == breakColumn)) {
     293            hit = true;
     294            break;
     295        }
     296    }
     297    if (!hit)
     298        return false;
     299
     300    if (hitBreakpoint)
     301        *hitBreakpoint = breakpoints[i];
     302
     303    if (breakpoints[i].condition.isEmpty())
     304        return true;
     305
     306    JSValue exception;
     307    JSValue result = DebuggerCallFrame::evaluateWithCallFrame(m_currentCallFrame, breakpoints[i].condition, exception);
     308    if (exception) {
     309        // An erroneous condition counts as "false".
     310        handleExceptionInBreakpointCondition(m_currentCallFrame, exception);
     311        return false;
     312    }
     313    return result.toBoolean(m_currentCallFrame);
     314}
     315
     316void Debugger::clearBreakpoints()
     317{
     318    m_topBreakpointID = noBreakpointID;
     319    m_breakpointIDToBreakpoint.clear();
     320    m_sourceIDToBreakpoints.clear();
     321
     322    updateNeedForOpDebugCallbacks();
     323}
     324
     325void Debugger::setBreakpointsActivated(bool activated)
     326{
     327    m_breakpointsActivated = activated;
     328}
     329
     330void Debugger::setPauseOnExceptionsState(PauseOnExceptionsState pause)
     331{
     332    m_pauseOnExceptionsState = pause;
     333}
     334
     335void Debugger::setPauseOnNextStatement(bool pause)
     336{
     337    m_pauseOnNextStatement = pause;
     338    if (pause)
     339        setShouldPause(true);
     340}
     341
     342void Debugger::breakProgram()
     343{
     344    if (m_isPaused || !m_currentCallFrame)
     345        return;
     346
     347    m_pauseOnNextStatement = true;
     348    setShouldPause(true);
     349    pauseIfNeeded(m_currentCallFrame);
     350}
     351
     352void Debugger::continueProgram()
     353{
     354    if (!m_isPaused)
     355        return;
     356
     357    m_pauseOnNextStatement = false;
     358    notifyDoneProcessingDebuggerEvents();
     359}
     360
     361void Debugger::stepIntoStatement()
     362{
     363    if (!m_isPaused)
     364        return;
     365
     366    m_pauseOnNextStatement = true;
     367    setShouldPause(true);
     368    notifyDoneProcessingDebuggerEvents();
     369}
     370
     371void Debugger::stepOverStatement()
     372{
     373    if (!m_isPaused)
     374        return;
     375
     376    m_pauseOnCallFrame = m_currentCallFrame;
     377    notifyDoneProcessingDebuggerEvents();
     378}
     379
     380void Debugger::stepOutOfFunction()
     381{
     382    if (!m_isPaused)
     383        return;
     384
     385    m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->callerFrameSkippingVMEntrySentinel() : 0;
     386    notifyDoneProcessingDebuggerEvents();
     387}
     388
     389void Debugger::updateCallFrame(CallFrame* callFrame)
     390{
     391    m_currentCallFrame = callFrame;
     392    SourceID sourceID = DebuggerCallFrame::sourceIDForCallFrame(callFrame);
     393    if (m_lastExecutedSourceID != sourceID) {
     394        m_lastExecutedLine = UINT_MAX;
     395        m_lastExecutedSourceID = sourceID;
     396    }
     397}
     398
     399void Debugger::updateCallFrameAndPauseIfNeeded(CallFrame* callFrame)
     400{
     401    updateCallFrame(callFrame);
     402    pauseIfNeeded(callFrame);
     403    if (!needsOpDebugCallbacks())
     404        m_currentCallFrame = 0;
     405}
     406
     407void Debugger::pauseIfNeeded(CallFrame* callFrame)
     408{
     409    if (m_isPaused)
     410        return;
     411
     412    JSGlobalObject* dynamicGlobalObject = callFrame->dynamicGlobalObject();
     413    if (!needPauseHandling(dynamicGlobalObject))
     414        return;
     415
     416    Breakpoint breakpoint;
     417    bool didHitBreakpoint = false;
     418    bool pauseNow = m_pauseOnNextStatement;
     419    pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame);
     420
     421    intptr_t sourceID = DebuggerCallFrame::sourceIDForCallFrame(m_currentCallFrame);
     422    TextPosition position = DebuggerCallFrame::positionForCallFrame(m_currentCallFrame);
     423    pauseNow |= didHitBreakpoint = hasBreakpoint(sourceID, position, &breakpoint);
     424    m_lastExecutedLine = position.m_line.zeroBasedInt();
     425    if (!pauseNow)
     426        return;
     427
     428    DebuggerCallFrameScope debuggerCallFrameScope(*this);
     429
     430    if (didHitBreakpoint) {
     431        handleBreakpointHit(breakpoint);
     432        if (breakpoint.autoContinue)
     433            return;
     434    }
     435
     436    m_pauseOnCallFrame = 0;
     437    m_pauseOnNextStatement = false;
     438    m_isPaused = true;
     439
     440    handlePause(m_reasonForPause, dynamicGlobalObject);
     441
     442    if (!m_pauseOnNextStatement && !m_pauseOnCallFrame) {
     443        setShouldPause(false);
     444        if (!needsOpDebugCallbacks())
     445            m_currentCallFrame = 0;
     446    }
     447
     448    m_isPaused = false;
     449}
     450
     451void Debugger::exception(CallFrame* callFrame, JSValue exception, bool hasHandler)
     452{
     453    if (m_isPaused)
     454        return;
     455
     456    PauseReasonDeclaration reason(*this, PausedForException);
     457    if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasHandler)) {
     458        m_pauseOnNextStatement = true;
     459        setShouldPause(true);
     460    }
     461
     462    m_hasHandlerForExceptionCallback = true;
     463    m_currentException = exception;
     464    updateCallFrameAndPauseIfNeeded(callFrame);
     465    m_currentException = JSValue();
     466    m_hasHandlerForExceptionCallback = false;
     467}
     468
     469void Debugger::atStatement(CallFrame* callFrame)
     470{
     471    if (m_isPaused)
     472        return;
     473
     474    PauseReasonDeclaration reason(*this, PausedAtStatement);
     475    updateCallFrameAndPauseIfNeeded(callFrame);
     476}
     477
     478void Debugger::callEvent(CallFrame* callFrame)
     479{
     480    if (m_isPaused)
     481        return;
     482
     483    PauseReasonDeclaration reason(*this, PausedAfterCall);
     484    updateCallFrameAndPauseIfNeeded(callFrame);
     485}
     486
     487void Debugger::returnEvent(CallFrame* callFrame)
     488{
     489    if (m_isPaused)
     490        return;
     491
     492    PauseReasonDeclaration reason(*this, PausedBeforeReturn);
     493    updateCallFrameAndPauseIfNeeded(callFrame);
     494
     495    // detach may have been called during pauseIfNeeded
     496    if (!m_currentCallFrame)
     497        return;
     498
     499    // Treat stepping over a return statement like stepping out.
     500    if (m_currentCallFrame == m_pauseOnCallFrame)
     501        m_pauseOnCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
     502
     503    m_currentCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
     504}
     505
     506void Debugger::willExecuteProgram(CallFrame* callFrame)
     507{
     508    if (m_isPaused)
     509        return;
     510
     511    PauseReasonDeclaration reason(*this, PausedAtStartOfProgram);
     512    // FIXME: This check for whether we're debugging a worker thread is a workaround
     513    // for https://bugs.webkit.org/show_bug.cgi?id=102637. Remove it when we rework
     514    // the debugger implementation to not require callbacks.
     515    if (!m_isInWorkerThread)
     516        updateCallFrameAndPauseIfNeeded(callFrame);
     517    else if (needsOpDebugCallbacks())
     518        updateCallFrame(callFrame);
     519}
     520
     521void Debugger::didExecuteProgram(CallFrame* callFrame)
     522{
     523    if (m_isPaused)
     524        return;
     525
     526    PauseReasonDeclaration reason(*this, PausedAtEndOfProgram);
     527    updateCallFrameAndPauseIfNeeded(callFrame);
     528
     529    // Treat stepping over the end of a program like stepping out.
     530    if (!m_currentCallFrame)
     531        return;
     532    if (m_currentCallFrame == m_pauseOnCallFrame) {
     533        m_pauseOnCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
     534        if (!m_currentCallFrame)
     535            return;
     536    }
     537    m_currentCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
     538}
     539
     540void Debugger::didReachBreakpoint(CallFrame* callFrame)
     541{
     542    if (m_isPaused)
     543        return;
     544
     545    PauseReasonDeclaration reason(*this, PausedForBreakpoint);
     546    m_pauseOnNextStatement = true;
     547    setShouldPause(true);
     548    updateCallFrameAndPauseIfNeeded(callFrame);
     549}
     550
     551DebuggerCallFrame* Debugger::currentDebuggerCallFrame() const
     552{
     553    ASSERT(m_currentDebuggerCallFrame);
     554    return m_currentDebuggerCallFrame.get();
    159555}
    160556
  • trunk/Source/JavaScriptCore/debugger/Debugger.h

    r157746 r158937  
    22 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
    33 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
    4  *  Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
     4 *  Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
    55 *
    66 *  This library is free software; you can redistribute it and/or
     
    2323#define Debugger_h
    2424
     25#include "Breakpoint.h"
     26#include "DebuggerCallFrame.h"
     27#include "DebuggerPrimitives.h"
     28#include "JSCJSValue.h"
     29#include <wtf/HashMap.h>
    2530#include <wtf/HashSet.h>
     31#include <wtf/RefPtr.h>
     32#include <wtf/Vector.h>
     33#include <wtf/text/TextPosition.h>
    2634
    2735namespace JSC {
    2836
    29 class DebuggerCallFrame;
    3037class ExecState;
     38class JSGlobalObject;
     39class SourceProvider;
    3140class VM;
    32 class JSGlobalObject;
    33 class JSValue;
    34 class SourceProvider;
    3541
    3642typedef ExecState CallFrame;
     
    3844class JS_EXPORT_PRIVATE Debugger {
    3945public:
    40     Debugger();
     46    Debugger(bool isInWorkerThread = false);
    4147    virtual ~Debugger();
    4248
     
    4450    static ptrdiff_t needsOpDebugCallbacksOffset() { return OBJECT_OFFSETOF(Debugger, m_needsOpDebugCallbacks); }
    4551
    46     bool shouldPause() const { return m_shouldPause; }
    47     void setShouldPause(bool);
     52    JSC::DebuggerCallFrame* currentDebuggerCallFrame() const;
     53    bool hasHandlerForExceptionCallback() const
     54    {
     55        ASSERT(m_reasonForPause == PausedForException);
     56        return m_hasHandlerForExceptionCallback;
     57    }
     58    JSValue currentException()
     59    {
     60        ASSERT(m_reasonForPause == PausedForException);
     61        return m_currentException;
     62    }
    4863
    49     bool needsExceptionCallbacks() const { return m_needsExceptionCallbacks; }
    50     void setNeedsExceptionCallbacks(bool);
    51 
    52     void incNumberOfBreakpoints() { updateNumberOfBreakpoints(m_numberOfBreakpoints + 1); }
    53     void decNumberOfBreakpoints()  { updateNumberOfBreakpoints(m_numberOfBreakpoints - 1); }
    54     void updateNumberOfBreakpoints(int);
     64    bool needsExceptionCallbacks() const { return m_pauseOnExceptionsState != DontPauseOnExceptions; }
    5565
    5666    void attach(JSGlobalObject*);
    5767    virtual void detach(JSGlobalObject*);
    5868
     69    BreakpointID setBreakpoint(Breakpoint, unsigned& actualLine, unsigned& actualColumn);
     70    void removeBreakpoint(BreakpointID);
     71    void clearBreakpoints();
     72    void setBreakpointsActivated(bool);
     73    void activateBreakpoints() { setBreakpointsActivated(true); }
     74    void deactivateBreakpoints() { setBreakpointsActivated(false); }
     75
     76    enum PauseOnExceptionsState {
     77        DontPauseOnExceptions,
     78        PauseOnAllExceptions,
     79        PauseOnUncaughtExceptions
     80    };
     81    PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; }
     82    void setPauseOnExceptionsState(PauseOnExceptionsState);
     83
     84    void setPauseOnNextStatement(bool);
     85    void breakProgram();
     86    void continueProgram();
     87    void stepIntoStatement();
     88    void stepOverStatement();
     89    void stepOutOfFunction();
     90
     91    bool isPaused() { return m_isPaused; }
     92
    5993    virtual void sourceParsed(ExecState*, SourceProvider*, int errorLineNumber, const WTF::String& errorMessage) = 0;
    6094
    61     virtual void exception(CallFrame*, JSValue exceptionValue, bool hasHandler) = 0;
    62     virtual void atStatement(CallFrame*) = 0;
    63     virtual void callEvent(CallFrame*) = 0;
    64     virtual void returnEvent(CallFrame*) = 0;
    65 
    66     virtual void willExecuteProgram(CallFrame*) = 0;
    67     virtual void didExecuteProgram(CallFrame*) = 0;
    68     virtual void didReachBreakpoint(CallFrame*) = 0;
     95    void exception(CallFrame*, JSValue exceptionValue, bool hasHandler);
     96    void atStatement(CallFrame*);
     97    void callEvent(CallFrame*);
     98    void returnEvent(CallFrame*);
     99    void willExecuteProgram(CallFrame*);
     100    void didExecuteProgram(CallFrame*);
     101    void didReachBreakpoint(CallFrame*);
    69102
    70103    void recompileAllJSFunctions(VM*);
    71104
     105protected:
     106    virtual bool needPauseHandling(JSGlobalObject*) { return false; }
     107    virtual void handleBreakpointHit(const Breakpoint&) { }
     108    virtual void handleExceptionInBreakpointCondition(ExecState*, JSValue exception) const { UNUSED_PARAM(exception); }
     109
     110    enum ReasonForPause {
     111        NotPaused,
     112        PausedForException,
     113        PausedAtStatement,
     114        PausedAfterCall,
     115        PausedBeforeReturn,
     116        PausedAtStartOfProgram,
     117        PausedAtEndOfProgram,
     118        PausedForBreakpoint
     119    };
     120
     121    virtual void handlePause(ReasonForPause, JSGlobalObject*) { }
     122    virtual void notifyDoneProcessingDebuggerEvents() { }
     123
    72124private:
     125    typedef HashMap<BreakpointID, Breakpoint*> BreakpointIDToBreakpointMap;
     126
     127    typedef Vector<Breakpoint> BreakpointsInLine;
     128    typedef HashMap<unsigned, BreakpointsInLine, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> LineToBreakpointsMap;
     129    typedef HashMap<SourceID, LineToBreakpointsMap> SourceIDToBreakpointsMap;
     130
     131    class PauseReasonDeclaration {
     132    public:
     133        PauseReasonDeclaration(Debugger& debugger, ReasonForPause reason)
     134            : m_debugger(debugger)
     135        {
     136            m_debugger.m_reasonForPause = reason;
     137        }
     138
     139        ~PauseReasonDeclaration()
     140        {
     141            m_debugger.m_reasonForPause = NotPaused;
     142        }
     143    private:
     144        Debugger& m_debugger;
     145    };
     146
     147    bool hasBreakpoint(SourceID, const TextPosition&, Breakpoint* hitBreakpoint) const;
     148
     149    bool shouldPause() const { return m_shouldPause; }
     150    void setShouldPause(bool);
    73151    void updateNeedForOpDebugCallbacks();
     152
     153    // These update functions are only needed because our current breakpoints are
     154    // key'ed off the source position instead of the bytecode PC. This ensures
     155    // that we don't break on the same line more than once. Once we switch to a
     156    // bytecode PC key'ed breakpoint, we will not need these anymore and should
     157    // be able to remove them.
     158    void updateCallFrame(JSC::CallFrame*);
     159    void updateCallFrameAndPauseIfNeeded(JSC::CallFrame*);
     160    void pauseIfNeeded(JSC::CallFrame*);
    74161
    75162    HashSet<JSGlobalObject*> m_globalObjects;
    76163
    77     bool m_needsExceptionCallbacks;
     164    PauseOnExceptionsState m_pauseOnExceptionsState;
     165    bool m_pauseOnNextStatement : 1;
     166    bool m_isPaused : 1;
     167    bool m_breakpointsActivated : 1;
     168    bool m_hasHandlerForExceptionCallback : 1;
     169    bool m_isInWorkerThread : 1;
     170
     171    ReasonForPause m_reasonForPause;
     172    JSValue m_currentException;
     173    CallFrame* m_pauseOnCallFrame;
     174    CallFrame* m_currentCallFrame;
     175    unsigned m_lastExecutedLine;
     176    SourceID m_lastExecutedSourceID;
     177
     178    BreakpointID m_topBreakpointID;
     179    BreakpointIDToBreakpointMap m_breakpointIDToBreakpoint;
     180    SourceIDToBreakpointsMap m_sourceIDToBreakpoints;
     181
    78182    bool m_needsOpDebugCallbacks;
    79183    bool m_shouldPause;
    80     int m_numberOfBreakpoints;
    81184
     185    RefPtr<JSC::DebuggerCallFrame> m_currentDebuggerCallFrame;
     186
     187    friend class DebuggerCallFrameScope;
    82188    friend class LLIntOffsetsExtractor;
    83189};
  • trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp

    r158862 r158937  
    8686}
    8787
    88 intptr_t DebuggerCallFrame::sourceID() const
    89 {
    90     ASSERT(isValid());
    91     if (!isValid())
    92         return 0;
     88SourceID DebuggerCallFrame::sourceID() const
     89{
     90    ASSERT(isValid());
     91    if (!isValid())
     92        return noSourceID;
    9393    return sourceIDForCallFrame(m_callFrame);
    9494}
     
    186186}
    187187
    188 intptr_t DebuggerCallFrame::sourceIDForCallFrame(CallFrame* callFrame)
     188SourceID DebuggerCallFrame::sourceIDForCallFrame(CallFrame* callFrame)
    189189{
    190190    ASSERT(callFrame);
    191191    CodeBlock* codeBlock = callFrame->codeBlock();
    192192    if (!codeBlock)
    193         return 0;
     193        return noSourceID;
    194194    return codeBlock->ownerExecutable()->sourceID();
    195195}
  • trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h

    r158862 r158937  
    3131
    3232#include "CallFrame.h"
     33#include "DebuggerPrimitives.h"
    3334#include <wtf/PassRefPtr.h>
    3435#include <wtf/RefCounted.h>
     
    3637
    3738namespace JSC {
    38    
     39
    3940class DebuggerCallFrame : public RefCounted<DebuggerCallFrame> {
    4041public:
     
    5152    JS_EXPORT_PRIVATE PassRefPtr<DebuggerCallFrame> callerFrame();
    5253    ExecState* exec() const { return m_callFrame; }
    53     JS_EXPORT_PRIVATE intptr_t sourceID() const;
     54    JS_EXPORT_PRIVATE SourceID sourceID() const;
    5455
    5556    // line and column are in base 0 e.g. the first line is line 0.
     
    7374    JS_EXPORT_PRIVATE static JSValue evaluateWithCallFrame(CallFrame*, const String& script, JSValue& exception);
    7475    JS_EXPORT_PRIVATE static TextPosition positionForCallFrame(CallFrame*);
    75     JS_EXPORT_PRIVATE static intptr_t sourceIDForCallFrame(CallFrame*);
     76    JS_EXPORT_PRIVATE static SourceID sourceIDForCallFrame(CallFrame*);
    7677    static JSValue thisValueForCallFrame(CallFrame*);
    7778
  • trunk/Source/WebCore/ChangeLog

    r158935 r158937  
     12013-11-08  Mark Lam  <mark.lam@apple.com>
     2
     3        Move breakpoint (and exception break) functionality into JSC::Debugger.
     4        https://bugs.webkit.org/show_bug.cgi?id=121796.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        No new tests.
     9
     10        - In ScriptDebugServer and JSC::Debugger, SourceID and BreakpointID are
     11          now numeric tokens.
     12
     13        - JSC::Debugger now tracks user defined breakpoints in a JSC::Breakpoint
     14          record. Previously, this info is tracked in the ScriptBreakpoint record
     15          in ScriptDebugServer. The only element of ScriptBreakpoint that is not
     16          being tracked by JSC::Breakpoint is the ScriptBreakpointAction.
     17             The ScriptBreakpointAction is still tracked by the ScriptDebugServer
     18          in a list keyed on the corresponding BreakpointID.
     19             The ScriptBreakpoint record is now only used as a means of passing
     20          breakpoint paramaters to the ScriptDebugServer.
     21
     22        - ScriptDebugServer now no longer accesses the JSC::CallFrame* directly.
     23          It always goes through the DebuggerCallFrame.
     24
     25        * GNUmakefile.list.am:
     26        * WebCore.vcxproj/WebCore.vcxproj:
     27        * WebCore.vcxproj/WebCore.vcxproj.filters:
     28        * WebCore.xcodeproj/project.pbxproj:
     29        * bindings/js/BreakpointID.h: Added.
     30        * bindings/js/ScriptDebugServer.cpp:
     31        (WebCore::ScriptDebugServer::ScriptDebugServer):
     32        (WebCore::ScriptDebugServer::setBreakpoint):
     33        (WebCore::ScriptDebugServer::removeBreakpoint):
     34        (WebCore::ScriptDebugServer::clearBreakpoints):
     35        (WebCore::ScriptDebugServer::dispatchDidPause):
     36        (WebCore::ScriptDebugServer::dispatchDidContinue):
     37        (WebCore::ScriptDebugServer::dispatchDidParseSource):
     38        (WebCore::ScriptDebugServer::notifyDoneProcessingDebuggerEvents):
     39        (WebCore::ScriptDebugServer::needPauseHandling):
     40        (WebCore::ScriptDebugServer::handleBreakpointHit):
     41        (WebCore::ScriptDebugServer::handleExceptionInBreakpointCondition):
     42        (WebCore::ScriptDebugServer::handlePause):
     43        * bindings/js/ScriptDebugServer.h:
     44        * bindings/js/SourceID.h: Added.
     45        * bindings/js/WorkerScriptDebugServer.cpp:
     46        (WebCore::WorkerScriptDebugServer::WorkerScriptDebugServer):
     47        * bindings/js/WorkerScriptDebugServer.h:
     48        * inspector/InspectorDebuggerAgent.cpp:
     49        (WebCore::InspectorDebuggerAgent::InspectorDebuggerAgent):
     50        (WebCore::parseLocation):
     51        (WebCore::InspectorDebuggerAgent::setBreakpoint):
     52        (WebCore::InspectorDebuggerAgent::continueToLocation):
     53        (WebCore::InspectorDebuggerAgent::resolveBreakpoint):
     54        (WebCore::InspectorDebuggerAgent::searchInContent):
     55        (WebCore::InspectorDebuggerAgent::getScriptSource):
     56        (WebCore::InspectorDebuggerAgent::didParseSource):
     57        (WebCore::InspectorDebuggerAgent::didPause):
     58        (WebCore::InspectorDebuggerAgent::clear):
     59        * inspector/InspectorDebuggerAgent.h:
     60        * inspector/ScriptDebugListener.h:
     61
    1622013-11-08  László Langó  <lango@inf.u-szeged.hu>
    263
  • trunk/Source/WebCore/GNUmakefile.list.am

    r158849 r158937  
    22472247        Source/WebCore/bindings/js/ArrayValue.cpp \
    22482248        Source/WebCore/bindings/js/ArrayValue.h \
     2249        Source/WebCore/bindings/js/BreakpointID.h \
    22492250        Source/WebCore/bindings/js/CachedScriptSourceProvider.h \
    22502251        Source/WebCore/bindings/js/CallbackFunction.cpp \
     
    24492450        Source/WebCore/bindings/js/SerializedScriptValue.cpp \
    24502451        Source/WebCore/bindings/js/SerializedScriptValue.h \
     2452        Source/WebCore/bindings/js/SourceID.h \
    24512453        Source/WebCore/bindings/js/WebCoreJSClientData.h \
    24522454        Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp \
  • trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj

    r158736 r158937  
    2030920309    <ClInclude Include="..\bindings\generic\RuntimeEnabledFeatures.h" />
    2031020310    <ClInclude Include="..\bindings\js\ArrayValue.h" />
     20311    <ClInclude Include="..\bindings\js\BreakpointID.h" />
    2031120312    <ClInclude Include="..\bindings\js\CachedScriptSourceProvider.h" />
    2031220313    <ClInclude Include="..\bindings\js\CallbackFunction.h" />
     
    2036020361    <ClInclude Include="..\bindings\js\ScriptWrappable.h" />
    2036120362    <ClInclude Include="..\bindings\js\SerializedScriptValue.h" />
     20363    <ClInclude Include="..\bindings\js\SourceID.h" />
    2036220364    <ClInclude Include="..\bindings\js\WebCoreJSClientData.h" />
    2036320365    <ClInclude Include="..\bindings\js\WorkerScriptController.h" />
  • trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters

    r158736 r158937  
    1133011330      <Filter>bindings\js</Filter>
    1133111331    </ClInclude>
     11332    <ClInclude Include="..\bindings\js\BreakpointID.h">
     11333      <Filter>bindings\js</Filter>
     11334    </ClInclude>
    1133211335    <ClInclude Include="..\bindings\js\CachedScriptSourceProvider.h">
    1133311336      <Filter>bindings\js</Filter>
     
    1146311466    </ClInclude>
    1146411467    <ClInclude Include="..\bindings\js\SerializedScriptValue.h">
     11468      <Filter>bindings\js</Filter>
     11469    </ClInclude>
     11470    <ClInclude Include="..\bindings\js\SourceID.h">
    1146511471      <Filter>bindings\js</Filter>
    1146611472    </ClInclude>
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r158853 r158937  
    53345334                CD61FE671794AADB004101EB /* MediaSourceRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B1A942E115B5CE2200D525D1 /* MediaSourceRegistry.cpp */; };
    53355335                CD61FE681794AADB004101EB /* MediaSourceRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = B1A942E215B5CE2200D525D1 /* MediaSourceRegistry.h */; };
    5336 
    53375336                CD641EB31818F5ED00EE4C41 /* MediaSourcePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = CD641EB11818F5ED00EE4C41 /* MediaSourcePrivate.h */; };
    53385337                CD641EB41818F5ED00EE4C41 /* SourceBufferPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = CD641EB21818F5ED00EE4C41 /* SourceBufferPrivate.h */; };
     
    62406239                FE16CFD5169D1DED00D3A0C7 /* DatabaseBackendSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE16CFD1169D1DEC00D3A0C7 /* DatabaseBackendSync.cpp */; };
    62416240                FE16CFD6169D1DED00D3A0C7 /* DatabaseBackendSync.h in Headers */ = {isa = PBXBuildFile; fileRef = FE16CFD2169D1DEC00D3A0C7 /* DatabaseBackendSync.h */; settings = {ATTRIBUTES = (Private, ); }; };
     6241                FE213B29182BE9F800AD2D12 /* SourceID.h in Headers */ = {isa = PBXBuildFile; fileRef = FE213B28182BE9F800AD2D12 /* SourceID.h */; settings = {ATTRIBUTES = (Private, ); }; };
    62426242                FE3371A2167C11D400EDB752 /* DatabaseBasicTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = FE3371A0167C11D400EDB752 /* DatabaseBasicTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
    62436243                FE36FD1516C7826500F887C1 /* ChangeVersionData.h in Headers */ = {isa = PBXBuildFile; fileRef = FE36FD1116C7826400F887C1 /* ChangeVersionData.h */; };
     
    62716271                FEBC5F3216BD0CC300659BD3 /* DatabaseBase.h in Headers */ = {isa = PBXBuildFile; fileRef = FEBC5F3016BD0CC300659BD3 /* DatabaseBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
    62726272                FED13D3A0CEA934600D89466 /* EditorIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = FED13D390CEA934600D89466 /* EditorIOS.mm */; };
     6273                FEDBFF16182B7A8D0017FA64 /* BreakpointID.h in Headers */ = {isa = PBXBuildFile; fileRef = FEDBFF14182B7A8D0017FA64 /* BreakpointID.h */; settings = {ATTRIBUTES = (Private, ); }; };
    62736274                FEDEF84116797108000E444A /* DatabaseStrategy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEDEF83F16797108000E444A /* DatabaseStrategy.cpp */; };
    62746275                FEDEF84216797108000E444A /* DatabaseStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = FEDEF84016797108000E444A /* DatabaseStrategy.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    1338913390                FE16CFD1169D1DEC00D3A0C7 /* DatabaseBackendSync.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseBackendSync.cpp; sourceTree = "<group>"; };
    1339013391                FE16CFD2169D1DEC00D3A0C7 /* DatabaseBackendSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseBackendSync.h; sourceTree = "<group>"; };
     13392                FE213B28182BE9F800AD2D12 /* SourceID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceID.h; sourceTree = "<group>"; };
    1339113393                FE3371A0167C11D400EDB752 /* DatabaseBasicTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseBasicTypes.h; sourceTree = "<group>"; };
    1339213394                FE36FD1116C7826400F887C1 /* ChangeVersionData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChangeVersionData.h; sourceTree = "<group>"; };
     
    1342013422                FEBC5F3016BD0CC300659BD3 /* DatabaseBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseBase.h; sourceTree = "<group>"; };
    1342113423                FED13D390CEA934600D89466 /* EditorIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EditorIOS.mm; sourceTree = "<group>"; };
     13424                FEDBFF14182B7A8D0017FA64 /* BreakpointID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BreakpointID.h; sourceTree = "<group>"; };
    1342213425                FEDEF83F16797108000E444A /* DatabaseStrategy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseStrategy.cpp; sourceTree = "<group>"; };
    1342313426                FEDEF84016797108000E444A /* DatabaseStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseStrategy.h; sourceTree = "<group>"; };
     
    1941819421                        isa = PBXGroup;
    1941919422                        children = (
     19423                                FE213B28182BE9F800AD2D12 /* SourceID.h */,
    1942019424                                BCCE58A71061E82F008FB35A /* Callback Objects */,
    1942119425                                BCCE58B41061E925008FB35A /* Constructors */,
     
    1942519429                                49B3760A15C6C6840059131D /* ArrayValue.cpp */,
    1942619430                                49B3760B15C6C6840059131D /* ArrayValue.h */,
     19431                                FEDBFF14182B7A8D0017FA64 /* BreakpointID.h */,
    1942719432                                BCD533630ED6848900887468 /* CachedScriptSourceProvider.h */,
    1942819433                                312D67B01535691F00563D0D /* Dictionary.cpp */,
     
    2184621851                        files = (
    2184721852                                932AD70617EFA2C40038F8FF /* MainFrame.h in Headers */,
     21853                                FEDBFF16182B7A8D0017FA64 /* BreakpointID.h in Headers */,
    2184821854                                FE115FAB167988CD00249134 /* AbstractDatabaseServer.h in Headers */,
    2184921855                                9A528E8417D7F52F00AA9518 /* FloatingObjects.h in Headers */,
     
    2188521891                                84D0C4061115F1EA0018AA34 /* AffineTransform.h in Headers */,
    2188621892                                CEDA12D7152CA1CB00D9E08D /* AlternativeTextClient.h in Headers */,
     21893                                FE213B29182BE9F800AD2D12 /* SourceID.h in Headers */,
    2188721894                                CE08C3D2152B599A0021B8C2 /* AlternativeTextController.h in Headers */,
    2188821895                                CE7B2DB31586ABAD0098B3FA /* AlternativeTextUIController.h in Headers */,
  • trunk/Source/WebCore/bindings/js/ScriptDebugServer.cpp

    r158862 r158937  
    11/*
    2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
    33 * Copyright (C) 2010-2011 Google Inc. All rights reserved.
    44 *
     
    5454namespace WebCore {
    5555
    56 class DebuggerCallFrameScope {
    57 public:
    58     DebuggerCallFrameScope(ScriptDebugServer& debugger)
    59         : m_debugger(debugger)
    60     {
    61         ASSERT(!m_debugger.m_currentDebuggerCallFrame);
    62         if (m_debugger.m_currentCallFrame)
    63             m_debugger.m_currentDebuggerCallFrame = DebuggerCallFrame::create(debugger.m_currentCallFrame);
    64     }
    65 
    66     ~DebuggerCallFrameScope()
    67     {
    68         if (m_debugger.m_currentDebuggerCallFrame) {
    69             m_debugger.m_currentDebuggerCallFrame->invalidate();
    70             m_debugger.m_currentDebuggerCallFrame = 0;
    71         }
    72     }
    73 
    74 private:
    75     ScriptDebugServer& m_debugger;
    76 };
    77 
    78 
    79 ScriptDebugServer::ScriptDebugServer()
    80     : m_callingListeners(false)
    81     , m_pauseOnExceptionsState(DontPauseOnExceptions)
    82     , m_pauseOnNextStatement(false)
    83     , m_paused(false)
     56ScriptDebugServer::ScriptDebugServer(bool isInWorkerThread)
     57    : Debugger(isInWorkerThread)
     58    , m_doneProcessingDebuggerEvents(true)
     59    , m_callingListeners(false)
    8460    , m_runningNestedMessageLoop(false)
    85     , m_doneProcessingDebuggerEvents(true)
    86     , m_breakpointsActivated(true)
    87     , m_pauseOnCallFrame(0)
    88     , m_currentCallFrame(0)
    8961    , m_recompileTimer(this, &ScriptDebugServer::recompileAllJSFunctions)
    90     , m_lastExecutedLine(-1)
    91     , m_lastExecutedSourceID(-1)
    9262{
    9363}
     
    9767}
    9868
    99 String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBreakpoint& scriptBreakpoint, int* actualLineNumber, int* actualColumnNumber)
    100 {
    101     intptr_t sourceIDValue = sourceID.toIntPtr();
    102     if (!sourceIDValue)
    103         return "";
    104     SourceIDToBreakpointsMap::iterator it = m_sourceIDToBreakpoints.find(sourceIDValue);
    105     if (it == m_sourceIDToBreakpoints.end())
    106         it = m_sourceIDToBreakpoints.set(sourceIDValue, LineToBreakpointsMap()).iterator;
    107     LineToBreakpointsMap::iterator breaksIt = it->value.find(scriptBreakpoint.lineNumber);
    108     if (breaksIt == it->value.end())
    109         breaksIt = it->value.set(scriptBreakpoint.lineNumber, BreakpointsInLine()).iterator;
    110 
    111     BreakpointsInLine& breaksVector = breaksIt->value;
    112     unsigned breaksCount = breaksVector.size();
    113     for (unsigned i = 0; i < breaksCount; i++) {
    114         if (breaksVector.at(i).columnNumber == scriptBreakpoint.columnNumber)
    115             return "";
    116     }
    117     breaksVector.append(scriptBreakpoint);
    118     incNumberOfBreakpoints();
    119 
    120     *actualLineNumber = scriptBreakpoint.lineNumber;
    121     *actualColumnNumber = scriptBreakpoint.columnNumber;
    122     return sourceID + ":" + String::number(scriptBreakpoint.lineNumber) + ":" + String::number(scriptBreakpoint.columnNumber);
    123 }
    124 
    125 void ScriptDebugServer::removeBreakpoint(const String& breakpointID)
    126 {
    127     Vector<String> tokens;
    128     breakpointID.split(":", tokens);
    129     if (tokens.size() != 3)
    130         return;
    131     bool success;
    132     intptr_t sourceIDValue = tokens[0].toIntPtr(&success);
    133     if (!success)
    134         return;
    135     unsigned lineNumber = tokens[1].toUInt(&success);
    136     if (!success)
    137         return;
    138     unsigned columnNumber = tokens[2].toUInt(&success);
    139     if (!success)
    140         return;
    141 
    142     SourceIDToBreakpointsMap::iterator it = m_sourceIDToBreakpoints.find(sourceIDValue);
    143     if (it == m_sourceIDToBreakpoints.end())
    144         return;
    145     LineToBreakpointsMap::iterator breaksIt = it->value.find(lineNumber);
    146     if (breaksIt == it->value.end())
    147         return;
    148 
    149     BreakpointsInLine& breaksVector = breaksIt->value;
    150     unsigned breaksCount = breaksVector.size();
    151     for (unsigned i = 0; i < breaksCount; i++) {
    152         if (breaksVector.at(i).columnNumber == static_cast<int>(columnNumber)) {
    153             breaksVector.remove(i);
    154             decNumberOfBreakpoints();
    155             break;
    156         }
    157     }
    158 }
    159 
    160 bool ScriptDebugServer::hasBreakpoint(intptr_t sourceID, const TextPosition& position, ScriptBreakpoint *hitBreakpoint) const
    161 {
    162     if (!m_breakpointsActivated)
    163         return false;
    164 
    165     SourceIDToBreakpointsMap::const_iterator it = m_sourceIDToBreakpoints.find(sourceID);
    166     if (it == m_sourceIDToBreakpoints.end())
    167         return false;
    168 
    169     int line = position.m_line.zeroBasedInt();
    170     int column = position.m_column.zeroBasedInt();
    171     if (line < 0 || column < 0)
    172         return false;
    173 
    174     LineToBreakpointsMap::const_iterator breaksIt = it->value.find(line);
    175     if (breaksIt == it->value.end())
    176         return false;
    177 
    178     bool hit = false;
    179     const BreakpointsInLine& breaksVector = breaksIt->value;
    180     unsigned breaksCount = breaksVector.size();
    181     unsigned i;
    182     for (i = 0; i < breaksCount; i++) {
    183         int breakLine = breaksVector.at(i).lineNumber;
    184         int breakColumn = breaksVector.at(i).columnNumber;
    185         // Since frontend truncates the indent, the first statement in a line must match the breakpoint (line,0).
    186         if ((line != m_lastExecutedLine && line == breakLine && !breakColumn)
    187             || (line == breakLine && column == breakColumn)) {
    188             hit = true;
    189             break;
    190         }
    191     }
    192     if (!hit)
    193         return false;
    194 
    195     if (hitBreakpoint)
    196         *hitBreakpoint = breaksVector.at(i);
    197 
    198     // An empty condition counts as no condition which is equivalent to "true".
    199     if (breaksVector.at(i).condition.isEmpty())
    200         return true;
    201 
    202     JSValue exception;
    203     JSValue result = DebuggerCallFrame::evaluateWithCallFrame(m_currentCallFrame, breaksVector.at(i).condition, exception);
    204     if (exception) {
    205         // An erroneous condition counts as "false".
    206         reportException(m_currentCallFrame, exception);
    207         return false;
    208     }
    209     return result.toBoolean(m_currentCallFrame);
     69BreakpointID ScriptDebugServer::setBreakpoint(SourceID sourceID, const ScriptBreakpoint& scriptBreakpoint, unsigned* actualLineNumber, unsigned* actualColumnNumber)
     70{
     71    if (!sourceID)
     72        return noBreakpointID;
     73
     74    JSC::Breakpoint breakpoint(sourceID, scriptBreakpoint.lineNumber, scriptBreakpoint.columnNumber, scriptBreakpoint.condition, scriptBreakpoint.autoContinue);
     75    BreakpointID id = Debugger::setBreakpoint(breakpoint, *actualLineNumber, *actualColumnNumber);
     76    if (id != noBreakpointID && !scriptBreakpoint.actions.isEmpty()) {
     77#ifndef NDEBUG
     78        BreakpointIDToActionsMap::iterator it = m_breakpointIDToActions.find(id);
     79        ASSERT(it == m_breakpointIDToActions.end());
     80#endif
     81        const Vector<ScriptBreakpointAction> &actions = scriptBreakpoint.actions;
     82        m_breakpointIDToActions.set(id, actions);
     83    }
     84    return id;
     85}
     86
     87void ScriptDebugServer::removeBreakpoint(BreakpointID id)
     88{
     89    ASSERT(id != noBreakpointID);
     90    BreakpointIDToActionsMap::iterator it = m_breakpointIDToActions.find(id);
     91    if (it != m_breakpointIDToActions.end())
     92        m_breakpointIDToActions.remove(it);
     93
     94    Debugger::removeBreakpoint(id);
    21095}
    21196
     
    235120}
    236121
    237 bool ScriptDebugServer::evaluateBreakpointActions(const ScriptBreakpoint& breakpoint) const
    238 {
    239     for (size_t i = 0; i < breakpoint.actions.size(); ++i) {
    240         if (!evaluateBreakpointAction(breakpoint.actions[i]))
    241             return false;
    242     }
    243 
    244     return true;
    245 }
    246 
    247122void ScriptDebugServer::clearBreakpoints()
    248123{
    249     m_sourceIDToBreakpoints.clear();
    250     updateNumberOfBreakpoints(0);
    251 }
    252 
    253 void ScriptDebugServer::setBreakpointsActivated(bool activated)
    254 {
    255     m_breakpointsActivated = activated;
    256 }
    257 
    258 void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pause)
    259 {
    260     m_pauseOnExceptionsState = pause;
    261     setNeedsExceptionCallbacks(pause != DontPauseOnExceptions);
    262 }
    263 
    264 void ScriptDebugServer::setPauseOnNextStatement(bool pause)
    265 {
    266     m_pauseOnNextStatement = pause;
    267     if (pause)
    268         setShouldPause(true);
    269 }
    270 
    271 void ScriptDebugServer::breakProgram()
    272 {
    273     if (m_paused || !m_currentCallFrame)
    274         return;
    275 
    276     m_pauseOnNextStatement = true;
    277     setShouldPause(true);
    278     pauseIfNeeded(m_currentCallFrame);
    279 }
    280 
    281 void ScriptDebugServer::continueProgram()
    282 {
    283     if (!m_paused)
    284         return;
    285 
    286     m_pauseOnNextStatement = false;
    287     m_doneProcessingDebuggerEvents = true;
    288 }
    289 
    290 void ScriptDebugServer::stepIntoStatement()
    291 {
    292     if (!m_paused)
    293         return;
    294 
    295     m_pauseOnNextStatement = true;
    296     setShouldPause(true);
    297     m_doneProcessingDebuggerEvents = true;
    298 }
    299 
    300 void ScriptDebugServer::stepOverStatement()
    301 {
    302     if (!m_paused)
    303         return;
    304 
    305     m_pauseOnCallFrame = m_currentCallFrame;
    306     m_doneProcessingDebuggerEvents = true;
    307 }
    308 
    309 void ScriptDebugServer::stepOutOfFunction()
    310 {
    311     if (!m_paused)
    312         return;
    313 
    314     m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->callerFrameSkippingVMEntrySentinel() : 0;
    315     m_doneProcessingDebuggerEvents = true;
     124    Debugger::clearBreakpoints();
     125    m_breakpointIDToActions.clear();
    316126}
    317127
     
    334144}
    335145
    336 DebuggerCallFrame* ScriptDebugServer::currentDebuggerCallFrame() const
    337 {
    338     ASSERT(m_currentDebuggerCallFrame);
    339     return m_currentDebuggerCallFrame.get();
    340 }
    341 
    342146void ScriptDebugServer::dispatchDidPause(ScriptDebugListener* listener)
    343147{
    344     ASSERT(m_paused);
     148    ASSERT(isPaused());
    345149    DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame();
    346150    JSGlobalObject* globalObject = debuggerCallFrame->scope()->globalObject();
     
    362166{
    363167    listener->didContinue();
    364     if (!m_pauseOnNextStatement && !m_pauseOnCallFrame) {
    365         setShouldPause(false);
    366         if (!needsOpDebugCallbacks())
    367             m_currentCallFrame = 0;
    368     }
    369168}
    370169
    371170void ScriptDebugServer::dispatchDidParseSource(const ListenerSet& listeners, SourceProvider* sourceProvider, bool isContentScript)
    372171{
    373     String sourceID = String::number(sourceProvider->asID());
     172    SourceID sourceID = sourceProvider->asID();
    374173
    375174    ScriptDebugListener::Script script;
     
    419218}
    420219
    421 void ScriptDebugServer::detach(JSGlobalObject* globalObject)
    422 {
    423     // If we're detaching from the currently executing global object, manually tear down our
    424     // stack, since we won't get further debugger callbacks to do so. Also, resume execution,
    425     // since there's no point in staying paused once a window closes.
    426     if (m_currentCallFrame && m_currentCallFrame->dynamicGlobalObject() == globalObject) {
    427         m_currentCallFrame = 0;
    428         m_pauseOnCallFrame = 0;
    429         continueProgram();
    430     }
    431     Debugger::detach(globalObject);
    432 }
    433 
    434220void ScriptDebugServer::sourceParsed(ExecState* exec, SourceProvider* sourceProvider, int errorLine, const String& errorMessage)
    435221{
     
    476262}
    477263
    478 void ScriptDebugServer::updateCallFrame(CallFrame* callFrame)
    479 {
    480     m_currentCallFrame = callFrame;
    481     intptr_t sourceID = DebuggerCallFrame::sourceIDForCallFrame(callFrame);
    482     if (m_lastExecutedSourceID != sourceID) {
    483         m_lastExecutedLine = -1;
    484         m_lastExecutedSourceID = sourceID;
    485     }
    486 }
    487 
    488 void ScriptDebugServer::updateCallFrameAndPauseIfNeeded(CallFrame* callFrame)
    489 {
    490     updateCallFrame(callFrame);
    491     pauseIfNeeded(callFrame);
    492     if (!needsOpDebugCallbacks())
    493         m_currentCallFrame = 0;
    494 }
    495 
    496 void ScriptDebugServer::pauseIfNeeded(CallFrame* callFrame)
    497 {
    498     if (m_paused)
    499         return;
    500  
    501     JSGlobalObject* dynamicGlobalObject = callFrame->dynamicGlobalObject();
    502     if (!getListenersForGlobalObject(dynamicGlobalObject))
    503         return;
    504 
    505     ScriptBreakpoint breakpoint;
    506     bool didHitBreakpoint = false;
    507     bool pauseNow = m_pauseOnNextStatement;
    508     pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame);
    509 
    510     intptr_t sourceID = DebuggerCallFrame::sourceIDForCallFrame(m_currentCallFrame);
    511     TextPosition position = DebuggerCallFrame::positionForCallFrame(m_currentCallFrame);
    512     pauseNow |= didHitBreakpoint = hasBreakpoint(sourceID, position, &breakpoint);
    513     m_lastExecutedLine = position.m_line.zeroBasedInt();
    514     if (!pauseNow)
    515         return;
    516 
    517     DebuggerCallFrameScope debuggerCallFrameScope(*this);
    518 
    519     if (didHitBreakpoint) {
    520         evaluateBreakpointActions(breakpoint);
    521         if (breakpoint.autoContinue)
    522             return;
    523     }
    524 
    525     m_pauseOnCallFrame = 0;
    526     m_pauseOnNextStatement = false;
    527     m_paused = true;
    528 
     264void ScriptDebugServer::notifyDoneProcessingDebuggerEvents()
     265{
     266    m_doneProcessingDebuggerEvents = true;
     267}
     268
     269bool ScriptDebugServer::needPauseHandling(JSGlobalObject* globalObject)
     270{
     271    return !!getListenersForGlobalObject(globalObject);
     272}
     273
     274void ScriptDebugServer::handleBreakpointHit(const JSC::Breakpoint& breakpoint)
     275{
     276    BreakpointIDToActionsMap::iterator it = m_breakpointIDToActions.find(breakpoint.id);
     277    if (it != m_breakpointIDToActions.end()) {
     278        BreakpointActions& actions = it->value;
     279        for (size_t i = 0; i < actions.size(); ++i) {
     280            if (!evaluateBreakpointAction(actions[i]))
     281                return;
     282        }
     283    }
     284}
     285
     286void ScriptDebugServer::handleExceptionInBreakpointCondition(JSC::ExecState* exec, JSC::JSValue exception) const
     287{
     288    reportException(exec, exception);
     289}
     290
     291void ScriptDebugServer::handlePause(Debugger::ReasonForPause, JSGlobalObject* dynamicGlobalObject)
     292{
    529293    dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidPause, dynamicGlobalObject);
    530294    didPause(dynamicGlobalObject);
     
    539303    didContinue(dynamicGlobalObject);
    540304    dispatchFunctionToListeners(&ScriptDebugServer::dispatchDidContinue, dynamicGlobalObject);
    541 
    542     m_paused = false;
    543 }
    544 
    545 void ScriptDebugServer::callEvent(CallFrame* callFrame)
    546 {
    547     if (!m_paused)
    548         updateCallFrameAndPauseIfNeeded(callFrame);
    549 }
    550 
    551 void ScriptDebugServer::atStatement(CallFrame* callFrame)
    552 {
    553     if (!m_paused)
    554         updateCallFrameAndPauseIfNeeded(callFrame);
    555 }
    556 
    557 void ScriptDebugServer::returnEvent(CallFrame* callFrame)
    558 {
    559     if (m_paused)
    560         return;
    561 
    562     updateCallFrameAndPauseIfNeeded(callFrame);
    563 
    564     // detach may have been called during pauseIfNeeded
    565     if (!m_currentCallFrame)
    566         return;
    567 
    568     // Treat stepping over a return statement like stepping out.
    569     if (m_currentCallFrame == m_pauseOnCallFrame)
    570         m_pauseOnCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
    571 
    572     m_currentCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
    573 }
    574 
    575 void ScriptDebugServer::exception(CallFrame* callFrame, JSValue, bool hasHandler)
    576 {
    577     if (m_paused)
    578         return;
    579 
    580     if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasHandler)) {
    581         m_pauseOnNextStatement = true;
    582         setShouldPause(true);
    583     }
    584 
    585     updateCallFrameAndPauseIfNeeded(callFrame);
    586 }
    587 
    588 void ScriptDebugServer::willExecuteProgram(CallFrame* callFrame)
    589 {
    590     if (!m_paused)
    591         updateCallFrameAndPauseIfNeeded(callFrame);
    592 }
    593 
    594 void ScriptDebugServer::didExecuteProgram(CallFrame* callFrame)
    595 {
    596     if (m_paused)
    597         return;
    598 
    599     updateCallFrameAndPauseIfNeeded(callFrame);
    600 
    601     // Treat stepping over the end of a program like stepping out.
    602     if (!m_currentCallFrame)
    603         return;
    604     if (m_currentCallFrame == m_pauseOnCallFrame) {
    605         m_pauseOnCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
    606         if (!m_currentCallFrame)
    607             return;
    608     }
    609     m_currentCallFrame = m_currentCallFrame->callerFrameSkippingVMEntrySentinel();
    610 }
    611 
    612 void ScriptDebugServer::didReachBreakpoint(CallFrame* callFrame)
    613 {
    614     if (m_paused)
    615         return;
    616 
    617     m_pauseOnNextStatement = true;
    618     setShouldPause(true);
    619     updateCallFrameAndPauseIfNeeded(callFrame);
    620 }
    621 
     305}
    622306void ScriptDebugServer::recompileAllJSFunctionsSoon()
    623307{
  • trunk/Source/WebCore/bindings/js/ScriptDebugServer.h

    r158862 r158937  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
    33 * Copyright (C) 2010-2011 Google Inc. All rights reserved.
    44 *
     
    3333#if ENABLE(JAVASCRIPT_DEBUGGER)
    3434
     35#include "BreakpointID.h"
     36#include "ScriptBreakpoint.h"
    3537#include "ScriptDebugListener.h"
    36 #include "ScriptBreakpoint.h"
     38#include "SourceID.h"
    3739#include "Timer.h"
    3840#include <debugger/Debugger.h>
     
    5557class ScriptValue;
    5658
    57 class ScriptDebugServer : protected JSC::Debugger {
     59class ScriptDebugServer : public JSC::Debugger {
    5860    WTF_MAKE_NONCOPYABLE(ScriptDebugServer); WTF_MAKE_FAST_ALLOCATED;
    5961public:
    60     String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber);
    61     void removeBreakpoint(const String& breakpointID);
     62    BreakpointID setBreakpoint(SourceID, const ScriptBreakpoint&, unsigned* actualLineNumber, unsigned* actualColumnNumber);
     63    void removeBreakpoint(BreakpointID);
    6264    void clearBreakpoints();
    63     void setBreakpointsActivated(bool activated);
    64     void activateBreakpoints() { setBreakpointsActivated(true); }
    65     void deactivateBreakpoints() { setBreakpointsActivated(false); }
    66 
    67     enum PauseOnExceptionsState {
    68         DontPauseOnExceptions,
    69         PauseOnAllExceptions,
    70         PauseOnUncaughtExceptions
    71     };
    72     PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; }
    73     void setPauseOnExceptionsState(PauseOnExceptionsState);
    74 
    75     void setPauseOnNextStatement(bool pause);
    76     void breakProgram();
    77     void continueProgram();
    78     void stepIntoStatement();
    79     void stepOverStatement();
    80     void stepOutOfFunction();
    8165
    8266    bool canSetScriptSource();
     
    9579    }
    9680
    97     bool isPaused() { return m_paused; }
    9881    bool runningNestedMessageLoop() { return m_runningNestedMessageLoop; }
    9982
     
    11396    typedef void (ScriptDebugServer::*JavaScriptExecutionCallback)(ScriptDebugListener*);
    11497
    115     ScriptDebugServer();
     98    ScriptDebugServer(bool isInWorkerThread = false);
    11699    ~ScriptDebugServer();
    117100
     
    124107    virtual bool isContentScript(JSC::ExecState*);
    125108
    126     bool hasBreakpoint(intptr_t sourceID, const TextPosition&, ScriptBreakpoint* hitBreakpoint) const;
    127109    bool evaluateBreakpointAction(const ScriptBreakpointAction&) const;
    128     bool evaluateBreakpointActions(const ScriptBreakpoint&) const;
    129110
    130111    void dispatchFunctionToListeners(JavaScriptExecutionCallback, JSC::JSGlobalObject*);
     
    135116    void dispatchFailedToParseSource(const ListenerSet& listeners, JSC::SourceProvider*, int errorLine, const String& errorMessage);
    136117
    137     // These update functions are only needed because our current breakpoints are
    138     // key'ed off the source position instead of the bytecode PC. This ensures
    139     // that we don't break on the same line more than once. Once we switch to a
    140     // bytecode PC key'ed breakpoint, we will not need these anymore and should
    141     // be able to remove them.
    142     void updateCallFrame(JSC::CallFrame*);
    143     void updateCallFrameAndPauseIfNeeded(JSC::CallFrame*);
    144     void pauseIfNeeded(JSC::CallFrame*);
     118    virtual void sourceParsed(JSC::ExecState*, JSC::SourceProvider*, int errorLine, const String& errorMsg) OVERRIDE;
    145119
    146     JSC::DebuggerCallFrame* currentDebuggerCallFrame() const;
     120    bool m_doneProcessingDebuggerEvents;
    147121
    148     virtual void detach(JSC::JSGlobalObject*) OVERRIDE;
     122private:
     123    typedef Vector<ScriptBreakpointAction> BreakpointActions;
     124    typedef HashMap<BreakpointID, BreakpointActions> BreakpointIDToActionsMap;
    149125
    150     virtual void sourceParsed(JSC::ExecState*, JSC::SourceProvider*, int errorLine, const String& errorMsg) OVERRIDE;
    151     virtual void callEvent(JSC::CallFrame*) OVERRIDE;
    152     virtual void atStatement(JSC::CallFrame*) OVERRIDE;
    153     virtual void returnEvent(JSC::CallFrame*) OVERRIDE;
    154     virtual void exception(JSC::CallFrame*, JSC::JSValue exceptionValue, bool hasHandler) OVERRIDE;
    155     virtual void willExecuteProgram(JSC::CallFrame*) OVERRIDE;
    156     virtual void didExecuteProgram(JSC::CallFrame*) OVERRIDE;
    157     virtual void didReachBreakpoint(JSC::CallFrame*) OVERRIDE;
    158 
    159     typedef Vector<ScriptBreakpoint> BreakpointsInLine;
    160     typedef HashMap<int, BreakpointsInLine, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> LineToBreakpointsMap;
    161     typedef HashMap<intptr_t, LineToBreakpointsMap> SourceIDToBreakpointsMap;
     126    virtual bool needPauseHandling(JSC::JSGlobalObject*) OVERRIDE;
     127    virtual void handleBreakpointHit(const JSC::Breakpoint&) OVERRIDE;
     128    virtual void handleExceptionInBreakpointCondition(JSC::ExecState*, JSC::JSValue exception) const OVERRIDE;
     129    virtual void handlePause(JSC::Debugger::ReasonForPause, JSC::JSGlobalObject*) OVERRIDE;
     130    virtual void notifyDoneProcessingDebuggerEvents() OVERRIDE;
    162131
    163132    bool m_callingListeners;
    164     PauseOnExceptionsState m_pauseOnExceptionsState;
    165     bool m_pauseOnNextStatement;
    166     bool m_paused;
    167133    bool m_runningNestedMessageLoop;
    168     bool m_doneProcessingDebuggerEvents;
    169     bool m_breakpointsActivated;
    170     JSC::CallFrame* m_pauseOnCallFrame;
    171     JSC::CallFrame* m_currentCallFrame;
    172     RefPtr<JSC::DebuggerCallFrame> m_currentDebuggerCallFrame;
    173     SourceIDToBreakpointsMap m_sourceIDToBreakpoints;
     134    BreakpointIDToActionsMap m_breakpointIDToActions;
    174135    Timer<ScriptDebugServer> m_recompileTimer;
    175 
    176     int m_lastExecutedLine;
    177     intptr_t m_lastExecutedSourceID;
    178136
    179137    friend class DebuggerCallFrameScope;
  • trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp

    r156936 r158937  
    11/*
    22 * Copyright (c) 2011 Google Inc. All rights reserved.
     3 * Copyright (c) 2013 Apple Inc. All rights reserved.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    4445
    4546WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerGlobalScope* context, const String& mode)
    46     : ScriptDebugServer()
     47    : ScriptDebugServer(true)
    4748    , m_workerGlobalScope(context)
    4849    , m_debuggerTaskMode(mode)
     
    5960    m_listeners.add(listener);
    6061    recompileAllJSFunctions(0);
    61 }
    62 
    63 void WorkerScriptDebugServer::willExecuteProgram(JSC::CallFrame* callFrame)
    64 {
    65     if (!m_paused)
    66         updateCallFrame(callFrame);
    6762}
    6863
  • trunk/Source/WebCore/bindings/js/WorkerScriptDebugServer.h

    r156374 r158937  
    6060    virtual bool isContentScript(JSC::ExecState*) OVERRIDE { return false; }
    6161
    62     virtual void willExecuteProgram(JSC::CallFrame*) OVERRIDE;
    63 
    6462    virtual void runEventLoopWhilePaused() OVERRIDE;
    6563
  • trunk/Source/WebCore/inspector/InspectorDebuggerAgent.cpp

    r158862 r158937  
    11/*
    2  * Copyright (C) 2010 Apple Inc. All rights reserved.
     2 * Copyright (C) 2010, 2013 Apple Inc. All rights reserved.
    33 * Copyright (C) 2010-2011 Google Inc. All rights reserved.
    44 *
     
    6060    , m_frontend(0)
    6161    , m_pausedScriptState(0)
     62    , m_continueToLocationBreakpointID(noBreakpointID)
    6263    , m_enabled(false)
    6364    , m_javaScriptPauseScheduled(false)
     
    303304}
    304305
    305 static bool parseLocation(ErrorString* errorString, RefPtr<InspectorObject> location, String* scriptID, int* lineNumber, int* columnNumber)
    306 {
    307     if (!location->getString("scriptId", scriptID) || !location->getNumber("lineNumber", lineNumber)) {
     306static bool parseLocation(ErrorString* errorString, InspectorObject* location, SourceID* sourceID, unsigned* lineNumber, unsigned* columnNumber)
     307{
     308    String scriptIDStr;
     309    if (!location->getString("scriptId", &scriptIDStr) || !location->getNumber("lineNumber", lineNumber)) {
    308310        // FIXME: replace with input validation.
     311        *sourceID = noSourceID;
    309312        *errorString = "scriptId and lineNumber are required.";
    310313        return false;
    311314    }
     315    *sourceID = scriptIDStr.toIntPtr();
    312316    *columnNumber = 0;
    313317    location->getNumber("columnNumber", columnNumber);
     
    317321void InspectorDebuggerAgent::setBreakpoint(ErrorString* errorString, const RefPtr<InspectorObject>& location, const RefPtr<InspectorObject>* options, TypeBuilder::Debugger::BreakpointId* outBreakpointIdentifier, RefPtr<TypeBuilder::Debugger::Location>& actualLocation)
    318322{
    319     String scriptID;
    320     int lineNumber;
    321     int columnNumber;
    322 
    323     if (!parseLocation(errorString, location, &scriptID, &lineNumber, &columnNumber))
     323    SourceID sourceID;
     324    unsigned lineNumber;
     325    unsigned columnNumber;
     326
     327    if (!parseLocation(errorString, location.get(), &sourceID, &lineNumber, &columnNumber))
    324328        return;
    325329
     
    337341        return;
    338342
    339     String breakpointIdentifier = scriptID + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
     343    String breakpointIdentifier = String::number(sourceID) + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
    340344    if (m_breakpointIdentifierToDebugServerBreakpointIDs.find(breakpointIdentifier) != m_breakpointIdentifierToDebugServerBreakpointIDs.end()) {
    341345        *errorString = "Breakpoint at specified location already exists.";
    342346        return;
    343347    }
     348
    344349    ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition, breakpointActions, autoContinue);
    345     actualLocation = resolveBreakpoint(breakpointIdentifier, scriptID, breakpoint);
     350    actualLocation = resolveBreakpoint(breakpointIdentifier, sourceID, breakpoint);
    346351    if (actualLocation)
    347352        *outBreakpointIdentifier = breakpointIdentifier;
     
    364369void InspectorDebuggerAgent::continueToLocation(ErrorString* errorString, const RefPtr<InspectorObject>& location)
    365370{
    366     if (!m_continueToLocationBreakpointID.isEmpty()) {
     371    if (m_continueToLocationBreakpointID != noBreakpointID) {
    367372        scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointID);
    368         m_continueToLocationBreakpointID = "";
    369     }
    370 
    371     String scriptID;
    372     int lineNumber;
    373     int columnNumber;
    374 
    375     if (!parseLocation(errorString, location, &scriptID, &lineNumber, &columnNumber))
     373        m_continueToLocationBreakpointID = noBreakpointID;
     374    }
     375
     376    SourceID sourceID;
     377    unsigned lineNumber;
     378    unsigned columnNumber;
     379
     380    if (!parseLocation(errorString, location.get(), &sourceID, &lineNumber, &columnNumber))
    376381        return;
    377382
    378383    ScriptBreakpoint breakpoint(lineNumber, columnNumber, "", false);
    379     m_continueToLocationBreakpointID = scriptDebugServer().setBreakpoint(scriptID, breakpoint, &lineNumber, &columnNumber);
     384    m_continueToLocationBreakpointID = scriptDebugServer().setBreakpoint(sourceID, breakpoint, &lineNumber, &columnNumber);
    380385    resume(errorString);
    381386}
    382387
    383 PassRefPtr<TypeBuilder::Debugger::Location> InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointIdentifier, const String& scriptID, const ScriptBreakpoint& breakpoint)
    384 {
    385     ScriptsMap::iterator scriptIterator = m_scripts.find(scriptID);
     388PassRefPtr<TypeBuilder::Debugger::Location> InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointIdentifier, SourceID sourceID, const ScriptBreakpoint& breakpoint)
     389{
     390    ScriptsMap::iterator scriptIterator = m_scripts.find(sourceID);
    386391    if (scriptIterator == m_scripts.end())
    387392        return 0;
     
    390395        return 0;
    391396
    392     int actualLineNumber;
    393     int actualColumnNumber;
    394     String debugServerBreakpointID = scriptDebugServer().setBreakpoint(scriptID, breakpoint, &actualLineNumber, &actualColumnNumber);
    395     if (debugServerBreakpointID.isEmpty())
     397    unsigned actualLineNumber;
     398    unsigned actualColumnNumber;
     399    BreakpointID debugServerBreakpointID = scriptDebugServer().setBreakpoint(sourceID, breakpoint, &actualLineNumber, &actualColumnNumber);
     400    if (debugServerBreakpointID == noBreakpointID)
    396401        return 0;
    397402
    398403    BreakpointIdentifierToDebugServerBreakpointIDsMap::iterator debugServerBreakpointIDsIterator = m_breakpointIdentifierToDebugServerBreakpointIDs.find(breakpointIdentifier);
    399404    if (debugServerBreakpointIDsIterator == m_breakpointIdentifierToDebugServerBreakpointIDs.end())
    400         debugServerBreakpointIDsIterator = m_breakpointIdentifierToDebugServerBreakpointIDs.set(breakpointIdentifier, Vector<String>()).iterator;
     405        debugServerBreakpointIDsIterator = m_breakpointIdentifierToDebugServerBreakpointIDs.set(breakpointIdentifier, Vector<BreakpointID>()).iterator;
    401406    debugServerBreakpointIDsIterator->value.append(debugServerBreakpointID);
    402407
    403408    RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
    404         .setScriptId(scriptID)
     409        .setScriptId(String::number(sourceID))
    405410        .setLineNumber(actualLineNumber);
    406411    location->setColumnNumber(actualColumnNumber);
     
    418423}
    419424
    420 void InspectorDebuggerAgent::searchInContent(ErrorString* error, const String& scriptID, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Array<WebCore::TypeBuilder::Page::SearchMatch>>& results)
     425void InspectorDebuggerAgent::searchInContent(ErrorString* error, const String& scriptIDStr, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Array<WebCore::TypeBuilder::Page::SearchMatch>>& results)
    421426{
    422427    bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
    423428    bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
    424429
    425     ScriptsMap::iterator it = m_scripts.find(scriptID);
     430    SourceID sourceID = scriptIDStr.toIntPtr();
     431    ScriptsMap::iterator it = m_scripts.find(sourceID);
    426432    if (it != m_scripts.end())
    427433        results = ContentSearchUtils::searchInTextByLines(it->value.source, query, caseSensitive, isRegex);
    428434    else
    429         *error = "No script for id: " + scriptID;
     435        *error = "No script for id: " + scriptIDStr;
    430436}
    431437
     
    442448}
    443449
    444 void InspectorDebuggerAgent::getScriptSource(ErrorString* error, const String& scriptID, String* scriptSource)
    445 {
    446     ScriptsMap::iterator it = m_scripts.find(scriptID);
     450void InspectorDebuggerAgent::getScriptSource(ErrorString* error, const String& scriptIDStr, String* scriptSource)
     451{
     452    SourceID sourceID = scriptIDStr.toIntPtr();
     453    ScriptsMap::iterator it = m_scripts.find(sourceID);
    447454    if (it != m_scripts.end())
    448455        *scriptSource = it->value.source;
    449456    else
    450         *error = "No script for id: " + scriptID;
     457        *error = "No script for id: " + scriptIDStr;
    451458}
    452459
     
    671678// JavaScriptDebugListener functions
    672679
    673 void InspectorDebuggerAgent::didParseSource(const String& scriptID, const Script& inScript)
     680void InspectorDebuggerAgent::didParseSource(SourceID sourceID, const Script& inScript)
    674681{
    675682    Script script = inScript;
     
    683690    String* sourceMapURLParam = script.sourceMappingURL.isNull() ? 0 : &script.sourceMappingURL;
    684691    const bool* isContentScript = script.isContentScript ? &script.isContentScript : 0;
    685     m_frontend->scriptParsed(scriptID, scriptURL, script.startLine, script.startColumn, script.endLine, script.endColumn, isContentScript, sourceMapURLParam, hasSourceURLParam);
    686 
    687     m_scripts.set(scriptID, script);
     692    String scriptIDStr = String::number(sourceID);
     693    m_frontend->scriptParsed(scriptIDStr, scriptURL, script.startLine, script.startColumn, script.endLine, script.endColumn, isContentScript, sourceMapURLParam, hasSourceURLParam);
     694
     695    m_scripts.set(sourceID, script);
    688696
    689697    if (scriptURL.isEmpty())
     
    710718        }
    711719
    712         RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(it->key, scriptID, breakpoint);
     720        RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(it->key, sourceID, breakpoint);
    713721        if (location)
    714722            m_frontend->breakpointResolved(it->key, location);
     
    739747    m_javaScriptPauseScheduled = false;
    740748
    741     if (!m_continueToLocationBreakpointID.isEmpty()) {
     749    if (m_continueToLocationBreakpointID != noBreakpointID) {
    742750        scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointID);
    743         m_continueToLocationBreakpointID = "";
     751        m_continueToLocationBreakpointID = noBreakpointID;
    744752    }
    745753    if (m_listener)
     
    768776    m_scripts.clear();
    769777    m_breakpointIdentifierToDebugServerBreakpointIDs.clear();
    770     m_continueToLocationBreakpointID = String();
     778    m_continueToLocationBreakpointID = noBreakpointID;
    771779    clearBreakDetails();
    772780    m_javaScriptPauseScheduled = false;
  • trunk/Source/WebCore/inspector/InspectorDebuggerAgent.h

    r158862 r158937  
    11/*
    2  * Copyright (C) 2010 Apple Inc. All rights reserved.
     2 * Copyright (C) 2010, 2013 Apple Inc. All rights reserved.
    33 * Copyright (C) 2010-2011 Google Inc. All rights reserved.
    44 *
     
    3232
    3333#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
     34#include "BreakpointID.h"
    3435#include "ConsoleAPITypes.h"
    3536#include "ConsoleTypes.h"
     
    4041#include "ScriptDebugListener.h"
    4142#include "ScriptState.h"
     43#include "SourceID.h"
    4244#include <wtf/Forward.h>
    4345#include <wtf/HashMap.h>
     
    150152    PassRefPtr<TypeBuilder::Array<TypeBuilder::Debugger::CallFrame>> currentCallFrames();
    151153
    152     virtual void didParseSource(const String& scriptID, const Script&) OVERRIDE FINAL;
     154    virtual void didParseSource(SourceID, const Script&) OVERRIDE FINAL;
    153155    virtual void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) OVERRIDE FINAL;
    154156
    155157    void setPauseOnExceptionsImpl(ErrorString*, int);
    156158
    157     PassRefPtr<TypeBuilder::Debugger::Location> resolveBreakpoint(const String& breakpointIdentifier, const String& scriptID, const ScriptBreakpoint&);
     159    PassRefPtr<TypeBuilder::Debugger::Location> resolveBreakpoint(const String& breakpointIdentifier, SourceID, const ScriptBreakpoint&);
    158160    void clear();
    159161    bool assertPaused(ErrorString*);
     
    162164    String sourceMapURLForScript(const Script&);
    163165
    164     typedef HashMap<String, Script> ScriptsMap;
    165     typedef HashMap<String, Vector<String>> BreakpointIdentifierToDebugServerBreakpointIDsMap;
     166    typedef HashMap<SourceID, Script> ScriptsMap;
     167    typedef HashMap<String, Vector<BreakpointID>> BreakpointIdentifierToDebugServerBreakpointIDsMap;
    166168    typedef HashMap<String, RefPtr<InspectorObject>> BreakpointIdentifierToBreakpointMap;
    167169
     
    173175    BreakpointIdentifierToDebugServerBreakpointIDsMap m_breakpointIdentifierToDebugServerBreakpointIDs;
    174176    BreakpointIdentifierToBreakpointMap m_javaScriptBreakpoints;
    175     String m_continueToLocationBreakpointID;
     177    BreakpointID m_continueToLocationBreakpointID;
    176178    InspectorFrontend::Debugger::Reason::Enum m_breakReason;
    177179    RefPtr<InspectorObject> m_breakAuxData;
  • trunk/Source/WebCore/inspector/ScriptDebugListener.h

    r158862 r158937  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
    33 * Copyright (C) 2010 Google Inc. All rights reserved.
    44 *
     
    3434
    3535#include "ScriptState.h"
     36#include "SourceID.h"
    3637#include <wtf/Forward.h>
    3738#include <wtf/text/WTFString.h>
     
    6667    virtual ~ScriptDebugListener() { }
    6768
    68     virtual void didParseSource(const String& scriptID, const Script&) = 0;
     69    virtual void didParseSource(SourceID, const Script&) = 0;
    6970    virtual void failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage) = 0;
    7071    virtual void didPause(JSC::ExecState*, const ScriptValue& callFrames, const ScriptValue& exception) = 0;
  • trunk/Source/WebKit/mac/ChangeLog

    r158884 r158937  
     12013-11-08  Mark Lam  <mark.lam@apple.com>
     2
     3        Move breakpoint (and exception break) functionality into JSC::Debugger.
     4        https://bugs.webkit.org/show_bug.cgi?id=121796.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * WebView/WebScriptDebugger.h:
     9        * WebView/WebScriptDebugger.mm:
     10        (WebScriptDebugger::WebScriptDebugger):
     11        (WebScriptDebugger::handlePause):
     12
    1132013-11-07  Joseph Pecoraro  <pecoraro@apple.com>
    214
  • trunk/Source/WebKit/mac/WebView/WebScriptDebugger.h

    r156374 r158937  
    5757private:
    5858    virtual void sourceParsed(JSC::ExecState*, JSC::SourceProvider*, int errorLine, const WTF::String& errorMsg) OVERRIDE;
    59     virtual void callEvent(JSC::CallFrame*) OVERRIDE { }
    60     virtual void atStatement(JSC::CallFrame*) OVERRIDE { }
    61     virtual void returnEvent(JSC::CallFrame*) OVERRIDE { }
    62     virtual void exception(JSC::CallFrame*, JSC::JSValue exceptionValue, bool hasHandler) OVERRIDE;
    63     virtual void willExecuteProgram(JSC::CallFrame*) OVERRIDE { }
    64     virtual void didExecuteProgram(JSC::CallFrame*) OVERRIDE { }
    65     virtual void didReachBreakpoint(JSC::CallFrame*) OVERRIDE { }
     59    virtual void handlePause(JSC::Debugger::ReasonForPause, JSC::JSGlobalObject*) OVERRIDE;
     60    virtual bool needPauseHandling(JSC::JSGlobalObject*) OVERRIDE { return true; }
    6661
    6762    bool m_callingDelegate;
  • trunk/Source/WebKit/mac/WebView/WebScriptDebugger.mm

    r158862 r158937  
    7676    , m_globalObject(globalObject->vm(), globalObject)
    7777{
     78    setPauseOnExceptionsState(PauseOnAllExceptions);
     79    deactivateBreakpoints();
    7880    attach(globalObject);
    79     setNeedsExceptionCallbacks(true);
    8081}
    8182
     
    118119}
    119120
    120 void WebScriptDebugger::exception(JSC::CallFrame* callFrame, JSC::JSValue exceptionValue, bool hasHandler)
     121void WebScriptDebugger::handlePause(Debugger::ReasonForPause reason, JSGlobalObject* globalObject)
    121122{
    122123    if (m_callingDelegate)
    123124        return;
    124125
     126    if (reason != Debugger::PausedForException)
     127        return;
     128
    125129    m_callingDelegate = true;
    126130
    127     WebFrame *webFrame = toWebFrame(callFrame->dynamicGlobalObject());
     131    WebFrame *webFrame = toWebFrame(globalObject);
    128132    WebView *webView = [webFrame webView];
    129     RefPtr<DebuggerCallFrame> debuggerCallFrame = DebuggerCallFrame::create(callFrame);
     133    DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame();
     134    JSValue exceptionValue = currentException();
    130135    String functionName = debuggerCallFrame->functionName();
    131136    RetainPtr<WebScriptCallFrame> webCallFrame = adoptNS([[WebScriptCallFrame alloc] _initWithGlobalObject:core(webFrame)->script().windowScriptObject() functionName:functionName exceptionValue:exceptionValue]);
     
    133138    WebScriptDebugDelegateImplementationCache* cache = WebViewGetScriptDebugDelegateImplementations(webView);
    134139    if (cache->exceptionWasRaisedFunc) {
    135         if (cache->exceptionWasRaisedExpectsHasHandlerFlag)
     140        if (cache->exceptionWasRaisedExpectsHasHandlerFlag) {
     141            bool hasHandler = hasHandlerForExceptionCallback();
    136142            CallScriptDebugDelegate(cache->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:hasHandler:sourceId:line:forWebFrame:), webCallFrame.get(), hasHandler, debuggerCallFrame->sourceID(), debuggerCallFrame->line(), webFrame);
    137         else
     143        } else
    138144            CallScriptDebugDelegate(cache->exceptionWasRaisedFunc, webView, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:), webCallFrame.get(), debuggerCallFrame->sourceID(), debuggerCallFrame->line(), webFrame);
    139145    }
Note: See TracChangeset for help on using the changeset viewer.