finally blocks should not set the exception stack trace when re-throwing the exception.
[WebKit-https.git] / Source / JavaScriptCore / debugger / Debugger.cpp
1 /*
2  *  Copyright (C) 2008, 2013, 2014 Apple Inc. All rights reserved.
3  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include "config.h"
23 #include "Debugger.h"
24
25 #include "CodeBlock.h"
26 #include "DebuggerCallFrame.h"
27 #include "Error.h"
28
29 #include "HeapIterationScope.h"
30 #include "Interpreter.h"
31 #include "JSCJSValueInlines.h"
32 #include "JSFunction.h"
33 #include "JSGlobalObject.h"
34 #include "JSCInlines.h"
35 #include "Parser.h"
36 #include "Protect.h"
37 #include "VMEntryScope.h"
38
39 namespace {
40
41 using namespace JSC;
42
43 class Recompiler : public MarkedBlock::VoidFunctor {
44 public:
45     Recompiler(JSC::Debugger*);
46     ~Recompiler();
47     IterationStatus operator()(JSCell*);
48
49 private:
50     typedef HashSet<FunctionExecutable*> FunctionExecutableSet;
51     typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;
52     
53     void visit(JSCell*);
54     
55     JSC::Debugger* m_debugger;
56     FunctionExecutableSet m_functionExecutables;
57     SourceProviderMap m_sourceProviders;
58 };
59
60 inline Recompiler::Recompiler(JSC::Debugger* debugger)
61     : m_debugger(debugger)
62 {
63 }
64
65 inline Recompiler::~Recompiler()
66 {
67     // Call sourceParsed() after reparsing all functions because it will execute
68     // JavaScript in the inspector.
69     SourceProviderMap::const_iterator end = m_sourceProviders.end();
70     for (SourceProviderMap::const_iterator iter = m_sourceProviders.begin(); iter != end; ++iter)
71         m_debugger->sourceParsed(iter->value, iter->key, -1, String());
72 }
73
74 inline void Recompiler::visit(JSCell* cell)
75 {
76     if (!cell->inherits(JSFunction::info()))
77         return;
78
79     JSFunction* function = jsCast<JSFunction*>(cell);
80     if (function->executable()->isHostFunction())
81         return;
82
83     FunctionExecutable* executable = function->jsExecutable();
84
85     // Check if the function is already in the set - if so,
86     // we've already retranslated it, nothing to do here.
87     if (!m_functionExecutables.add(executable).isNewEntry)
88         return;
89
90     ExecState* exec = function->scope()->globalObject()->JSGlobalObject::globalExec();
91     executable->clearCodeIfNotCompiling();
92     executable->clearUnlinkedCodeForRecompilationIfNotCompiling();
93     if (m_debugger == function->scope()->globalObject()->debugger())
94         m_sourceProviders.add(executable->source().provider(), exec);
95 }
96
97 inline IterationStatus Recompiler::operator()(JSCell* cell)
98 {
99     visit(cell);
100     return IterationStatus::Continue;
101 }
102
103 } // namespace
104
105 namespace JSC {
106
107 class DebuggerPausedScope {
108 public:
109     DebuggerPausedScope(Debugger& debugger)
110         : m_debugger(debugger)
111     {
112         ASSERT(!m_debugger.m_currentDebuggerCallFrame);
113         if (m_debugger.m_currentCallFrame)
114             m_debugger.m_currentDebuggerCallFrame = DebuggerCallFrame::create(debugger.m_currentCallFrame);
115     }
116
117     ~DebuggerPausedScope()
118     {
119         if (m_debugger.m_currentDebuggerCallFrame) {
120             m_debugger.m_currentDebuggerCallFrame->invalidate();
121             m_debugger.m_currentDebuggerCallFrame = 0;
122         }
123     }
124
125 private:
126     Debugger& m_debugger;
127 };
128
129 // This is very similar to TemporaryChange<bool>, but that cannot be used
130 // as the m_isPaused field uses only one bit.
131 class TemporaryPausedState {
132 public:
133     TemporaryPausedState(Debugger& debugger)
134         : m_debugger(debugger)
135     {
136         ASSERT(!m_debugger.m_isPaused);
137         m_debugger.m_isPaused = true;
138     }
139
140     ~TemporaryPausedState()
141     {
142         m_debugger.m_isPaused = false;
143     }
144
145 private:
146     Debugger& m_debugger;
147 };
148
149 template<typename Functor>
150 void Debugger::forEachCodeBlock(Functor& functor)
151 {
152     m_vm->prepareToDiscardCode();
153     m_vm->heap.forEachCodeBlock(functor);
154 }
155
156 Debugger::Debugger(bool isInWorkerThread)
157     : m_vm(nullptr)
158     , m_pauseOnExceptionsState(DontPauseOnExceptions)
159     , m_pauseOnNextStatement(false)
160     , m_isPaused(false)
161     , m_breakpointsActivated(true)
162     , m_hasHandlerForExceptionCallback(false)
163     , m_isInWorkerThread(isInWorkerThread)
164     , m_steppingMode(SteppingModeDisabled)
165     , m_reasonForPause(NotPaused)
166     , m_pauseOnCallFrame(0)
167     , m_currentCallFrame(0)
168     , m_lastExecutedLine(UINT_MAX)
169     , m_lastExecutedSourceID(noSourceID)
170     , m_topBreakpointID(noBreakpointID)
171     , m_pausingBreakpointID(noBreakpointID)
172 {
173 }
174
175 Debugger::~Debugger()
176 {
177     HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end();
178     for (HashSet<JSGlobalObject*>::iterator it = m_globalObjects.begin(); it != end; ++it)
179         (*it)->setDebugger(0);
180 }
181
182 void Debugger::attach(JSGlobalObject* globalObject)
183 {
184     ASSERT(!globalObject->debugger());
185     if (!m_vm)
186         m_vm = &globalObject->vm();
187     else
188         ASSERT(m_vm == &globalObject->vm());
189     globalObject->setDebugger(this);
190     m_globalObjects.add(globalObject);
191 }
192
193 void Debugger::detach(JSGlobalObject* globalObject, ReasonForDetach reason)
194 {
195     // If we're detaching from the currently executing global object, manually tear down our
196     // stack, since we won't get further debugger callbacks to do so. Also, resume execution,
197     // since there's no point in staying paused once a window closes.
198     if (m_currentCallFrame && m_currentCallFrame->vmEntryGlobalObject() == globalObject) {
199         m_currentCallFrame = 0;
200         m_pauseOnCallFrame = 0;
201         continueProgram();
202     }
203
204     ASSERT(m_globalObjects.contains(globalObject));
205     m_globalObjects.remove(globalObject);
206
207     // If the globalObject is destructing, then its CodeBlocks will also be
208     // destructed. There is no need to do the debugger requests clean up, and
209     // it is not safe to access those CodeBlocks at this time anyway.
210     if (reason != GlobalObjectIsDestructing)
211         clearDebuggerRequests(globalObject);
212
213     globalObject->setDebugger(0);
214     if (!m_globalObjects.size())
215         m_vm = nullptr;
216 }
217
218 bool Debugger::isAttached(JSGlobalObject* globalObject)
219 {
220     return globalObject->debugger() == this;
221 }
222
223 class Debugger::SetSteppingModeFunctor {
224 public:
225     SetSteppingModeFunctor(Debugger* debugger, SteppingMode mode)
226         : m_debugger(debugger)
227         , m_mode(mode)
228     {
229     }
230
231     bool operator()(CodeBlock* codeBlock)
232     {
233         if (m_debugger == codeBlock->globalObject()->debugger()) {
234             if (m_mode == SteppingModeEnabled)
235                 codeBlock->setSteppingMode(CodeBlock::SteppingModeEnabled);
236             else
237                 codeBlock->setSteppingMode(CodeBlock::SteppingModeDisabled);
238         }
239         return false;
240     }
241
242 private:
243     Debugger* m_debugger;
244     SteppingMode m_mode;
245 };
246
247 void Debugger::setSteppingMode(SteppingMode mode)
248 {
249     if (mode == m_steppingMode || !m_vm)
250         return;
251
252     m_vm->prepareToDiscardCode();
253
254     m_steppingMode = mode;
255     SetSteppingModeFunctor functor(this, mode);
256     m_vm->heap.forEachCodeBlock(functor);
257 }
258
259 void Debugger::registerCodeBlock(CodeBlock* codeBlock)
260 {
261     // FIXME: We should never have to jettison a code block (due to pending breakpoints
262     // or stepping mode) that is being registered. operationOptimize() should have
263     // prevented the optimizing of such code blocks in the first place. Find a way to
264     // express this with greater clarity in the code. See <https://webkit.org/b131771>.
265     applyBreakpoints(codeBlock);
266     if (isStepping())
267         codeBlock->setSteppingMode(CodeBlock::SteppingModeEnabled);
268 }
269
270 void Debugger::toggleBreakpoint(CodeBlock* codeBlock, Breakpoint& breakpoint, BreakpointState enabledOrNot)
271 {
272     ScriptExecutable* executable = codeBlock->ownerExecutable();
273
274     SourceID sourceID = static_cast<SourceID>(executable->sourceID());
275     if (breakpoint.sourceID != sourceID)
276         return;
277
278     unsigned line = breakpoint.line;
279     unsigned column = breakpoint.column;
280
281     unsigned startLine = executable->firstLine();
282     unsigned startColumn = executable->startColumn();
283     unsigned endLine = executable->lastLine();
284     unsigned endColumn = executable->endColumn();
285
286     // Inspector breakpoint line and column values are zero-based but the executable
287     // and CodeBlock line and column values are one-based.
288     line += 1;
289     column = column ? column + 1 : Breakpoint::unspecifiedColumn;
290
291     if (line < startLine || line > endLine)
292         return;
293     if (column != Breakpoint::unspecifiedColumn) {
294         if (line == startLine && column < startColumn)
295             return;
296         if (line == endLine && column > endColumn)
297             return;
298     }
299     if (!codeBlock->hasOpDebugForLineAndColumn(line, column))
300         return;
301
302     if (enabledOrNot == BreakpointEnabled)
303         codeBlock->addBreakpoint(1);
304     else
305         codeBlock->removeBreakpoint(1);
306 }
307
308 void Debugger::applyBreakpoints(CodeBlock* codeBlock)
309 {
310     BreakpointIDToBreakpointMap& breakpoints = m_breakpointIDToBreakpoint;
311     for (auto it = breakpoints.begin(); it != breakpoints.end(); ++it) {
312         Breakpoint& breakpoint = *it->value;
313         toggleBreakpoint(codeBlock, breakpoint, BreakpointEnabled);
314     }
315 }
316
317 class Debugger::ToggleBreakpointFunctor {
318 public:
319     ToggleBreakpointFunctor(Debugger* debugger, Breakpoint& breakpoint, BreakpointState enabledOrNot)
320         : m_debugger(debugger)
321         , m_breakpoint(breakpoint)
322         , m_enabledOrNot(enabledOrNot)
323     {
324     }
325
326     bool operator()(CodeBlock* codeBlock)
327     {
328         if (m_debugger == codeBlock->globalObject()->debugger())
329             m_debugger->toggleBreakpoint(codeBlock, m_breakpoint, m_enabledOrNot);
330         return false;
331     }
332
333 private:
334     Debugger* m_debugger;
335     Breakpoint& m_breakpoint;
336     BreakpointState m_enabledOrNot;
337 };
338
339 void Debugger::toggleBreakpoint(Breakpoint& breakpoint, Debugger::BreakpointState enabledOrNot)
340 {
341     if (!m_vm)
342         return;
343     ToggleBreakpointFunctor functor(this, breakpoint, enabledOrNot);
344     forEachCodeBlock(functor);
345 }
346
347 void Debugger::recompileAllJSFunctions(VM* vm)
348 {
349     // If JavaScript is running, it's not safe to recompile, since we'll end
350     // up throwing away code that is live on the stack.
351     if (vm->entryScope) {
352         auto listener = [] (VM& vm, JSGlobalObject* globalObject) 
353         {
354             if (Debugger* debugger = globalObject->debugger())
355                 debugger->recompileAllJSFunctions(&vm);
356         };
357
358         vm->entryScope->setEntryScopeDidPopListener(this, listener);
359         return;
360     }
361
362     vm->prepareToDiscardCode();
363
364     Recompiler recompiler(this);
365     HeapIterationScope iterationScope(vm->heap);
366     vm->heap.objectSpace().forEachLiveCell(iterationScope, recompiler);
367 }
368
369 BreakpointID Debugger::setBreakpoint(Breakpoint breakpoint, unsigned& actualLine, unsigned& actualColumn)
370 {
371     SourceID sourceID = breakpoint.sourceID;
372     unsigned line = breakpoint.line;
373     unsigned column = breakpoint.column;
374
375     SourceIDToBreakpointsMap::iterator it = m_sourceIDToBreakpoints.find(sourceID);
376     if (it == m_sourceIDToBreakpoints.end())
377         it = m_sourceIDToBreakpoints.set(sourceID, LineToBreakpointsMap()).iterator;
378     LineToBreakpointsMap::iterator breaksIt = it->value.find(line);
379     if (breaksIt == it->value.end())
380         breaksIt = it->value.set(line, adoptRef(new BreakpointsList)).iterator;
381
382     BreakpointsList& breakpoints = *breaksIt->value;
383     for (Breakpoint* current = breakpoints.head(); current; current = current->next()) {
384         if (current->column == column) {
385             // The breakpoint already exists. We're not allowed to create a new
386             // breakpoint at this location. Rather than returning the breakpointID
387             // of the pre-existing breakpoint, we need to return noBreakpointID
388             // to indicate that we're not creating a new one.
389             return noBreakpointID;
390         }
391     }
392
393     BreakpointID id = ++m_topBreakpointID;
394     RELEASE_ASSERT(id != noBreakpointID);
395
396     breakpoint.id = id;
397     actualLine = line;
398     actualColumn = column;
399
400     Breakpoint* newBreakpoint = new Breakpoint(breakpoint);
401     breakpoints.append(newBreakpoint);
402     m_breakpointIDToBreakpoint.set(id, newBreakpoint);
403
404     toggleBreakpoint(breakpoint, BreakpointEnabled);
405
406     return id;
407 }
408
409 void Debugger::removeBreakpoint(BreakpointID id)
410 {
411     ASSERT(id != noBreakpointID);
412
413     BreakpointIDToBreakpointMap::iterator idIt = m_breakpointIDToBreakpoint.find(id);
414     ASSERT(idIt != m_breakpointIDToBreakpoint.end());
415     Breakpoint* breakpoint = idIt->value;
416
417     SourceID sourceID = breakpoint->sourceID;
418     ASSERT(sourceID);
419     SourceIDToBreakpointsMap::iterator it = m_sourceIDToBreakpoints.find(sourceID);
420     ASSERT(it != m_sourceIDToBreakpoints.end());
421     LineToBreakpointsMap::iterator breaksIt = it->value.find(breakpoint->line);
422     ASSERT(breaksIt != it->value.end());
423
424     toggleBreakpoint(*breakpoint, BreakpointDisabled);
425
426     BreakpointsList& breakpoints = *breaksIt->value;
427 #if !ASSERT_DISABLED
428     bool found = false;
429     for (Breakpoint* current = breakpoints.head(); current && !found; current = current->next()) {
430         if (current->id == breakpoint->id)
431             found = true;
432     }
433     ASSERT(found);
434 #endif
435
436     m_breakpointIDToBreakpoint.remove(idIt);
437     breakpoints.remove(breakpoint);
438     delete breakpoint;
439
440     if (breakpoints.isEmpty()) {
441         it->value.remove(breaksIt);
442         if (it->value.isEmpty())
443             m_sourceIDToBreakpoints.remove(it);
444     }
445 }
446
447 bool Debugger::hasBreakpoint(SourceID sourceID, const TextPosition& position, Breakpoint *hitBreakpoint)
448 {
449     if (!m_breakpointsActivated)
450         return false;
451
452     SourceIDToBreakpointsMap::const_iterator it = m_sourceIDToBreakpoints.find(sourceID);
453     if (it == m_sourceIDToBreakpoints.end())
454         return false;
455
456     unsigned line = position.m_line.zeroBasedInt();
457     unsigned column = position.m_column.zeroBasedInt();
458
459     LineToBreakpointsMap::const_iterator breaksIt = it->value.find(line);
460     if (breaksIt == it->value.end())
461         return false;
462
463     bool hit = false;
464     const BreakpointsList& breakpoints = *breaksIt->value;
465     Breakpoint* breakpoint;
466     for (breakpoint = breakpoints.head(); breakpoint; breakpoint = breakpoint->next()) {
467         unsigned breakLine = breakpoint->line;
468         unsigned breakColumn = breakpoint->column;
469         // Since frontend truncates the indent, the first statement in a line must match the breakpoint (line,0).
470         ASSERT(this == m_currentCallFrame->codeBlock()->globalObject()->debugger());
471         if ((line != m_lastExecutedLine && line == breakLine && !breakColumn)
472             || (line == breakLine && column == breakColumn)) {
473             hit = true;
474             break;
475         }
476     }
477     if (!hit)
478         return false;
479
480     if (hitBreakpoint)
481         *hitBreakpoint = *breakpoint;
482
483     if (breakpoint->condition.isEmpty())
484         return true;
485
486     // We cannot stop in the debugger while executing condition code,
487     // so make it looks like the debugger is already paused.
488     TemporaryPausedState pausedState(*this);
489
490     Exception* exception;
491     DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame();
492     JSValue result = debuggerCallFrame->evaluate(breakpoint->condition, exception);
493
494     // We can lose the debugger while executing JavaScript.
495     if (!m_currentCallFrame)
496         return false;
497
498     if (exception) {
499         // An erroneous condition counts as "false".
500         handleExceptionInBreakpointCondition(m_currentCallFrame, exception);
501         return false;
502     }
503
504     return result.toBoolean(m_currentCallFrame);
505 }
506
507 class Debugger::ClearCodeBlockDebuggerRequestsFunctor {
508 public:
509     ClearCodeBlockDebuggerRequestsFunctor(Debugger* debugger)
510         : m_debugger(debugger)
511     {
512     }
513
514     bool operator()(CodeBlock* codeBlock)
515     {
516         if (codeBlock->hasDebuggerRequests() && m_debugger == codeBlock->globalObject()->debugger())
517             codeBlock->clearDebuggerRequests();
518         return false;
519     }
520
521 private:
522     Debugger* m_debugger;
523 };
524
525 void Debugger::clearBreakpoints()
526 {
527     m_topBreakpointID = noBreakpointID;
528     m_breakpointIDToBreakpoint.clear();
529     m_sourceIDToBreakpoints.clear();
530
531     if (!m_vm)
532         return;
533     ClearCodeBlockDebuggerRequestsFunctor functor(this);
534     forEachCodeBlock(functor);
535 }
536
537 class Debugger::ClearDebuggerRequestsFunctor {
538 public:
539     ClearDebuggerRequestsFunctor(JSGlobalObject* globalObject)
540         : m_globalObject(globalObject)
541     {
542     }
543
544     bool operator()(CodeBlock* codeBlock)
545     {
546         if (codeBlock->hasDebuggerRequests() && m_globalObject == codeBlock->globalObject())
547             codeBlock->clearDebuggerRequests();
548         return false;
549     }
550
551 private:
552     JSGlobalObject* m_globalObject;
553 };
554
555 void Debugger::clearDebuggerRequests(JSGlobalObject* globalObject)
556 {
557     ASSERT(m_vm);
558     ClearDebuggerRequestsFunctor functor(globalObject);
559     forEachCodeBlock(functor);
560 }
561
562 void Debugger::setBreakpointsActivated(bool activated)
563 {
564     m_breakpointsActivated = activated;
565 }
566
567 void Debugger::setPauseOnExceptionsState(PauseOnExceptionsState pause)
568 {
569     m_pauseOnExceptionsState = pause;
570 }
571
572 void Debugger::setPauseOnNextStatement(bool pause)
573 {
574     m_pauseOnNextStatement = pause;
575     if (pause)
576         setSteppingMode(SteppingModeEnabled);
577 }
578
579 void Debugger::breakProgram()
580 {
581     if (m_isPaused)
582         return;
583
584     m_pauseOnNextStatement = true;
585     setSteppingMode(SteppingModeEnabled);
586     m_currentCallFrame = m_vm->topCallFrame;
587     ASSERT(m_currentCallFrame);
588     pauseIfNeeded(m_currentCallFrame);
589 }
590
591 void Debugger::continueProgram()
592 {
593     if (!m_isPaused)
594         return;
595
596     m_pauseOnNextStatement = false;
597     notifyDoneProcessingDebuggerEvents();
598 }
599
600 void Debugger::stepIntoStatement()
601 {
602     if (!m_isPaused)
603         return;
604
605     m_pauseOnNextStatement = true;
606     setSteppingMode(SteppingModeEnabled);
607     notifyDoneProcessingDebuggerEvents();
608 }
609
610 void Debugger::stepOverStatement()
611 {
612     if (!m_isPaused)
613         return;
614
615     m_pauseOnCallFrame = m_currentCallFrame;
616     notifyDoneProcessingDebuggerEvents();
617 }
618
619 void Debugger::stepOutOfFunction()
620 {
621     if (!m_isPaused)
622         return;
623
624     VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
625     m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->callerFrame(topVMEntryFrame) : 0;
626     notifyDoneProcessingDebuggerEvents();
627 }
628
629 void Debugger::updateCallFrame(CallFrame* callFrame)
630 {
631     m_currentCallFrame = callFrame;
632     SourceID sourceID = DebuggerCallFrame::sourceIDForCallFrame(callFrame);
633     if (m_lastExecutedSourceID != sourceID) {
634         m_lastExecutedLine = UINT_MAX;
635         m_lastExecutedSourceID = sourceID;
636     }
637 }
638
639 void Debugger::updateCallFrameAndPauseIfNeeded(CallFrame* callFrame)
640 {
641     updateCallFrame(callFrame);
642     pauseIfNeeded(callFrame);
643     if (!isStepping())
644         m_currentCallFrame = 0;
645 }
646
647 void Debugger::pauseIfNeeded(CallFrame* callFrame)
648 {
649     if (m_isPaused)
650         return;
651
652     JSGlobalObject* vmEntryGlobalObject = callFrame->vmEntryGlobalObject();
653     if (!needPauseHandling(vmEntryGlobalObject))
654         return;
655
656     Breakpoint breakpoint;
657     bool didHitBreakpoint = false;
658     bool pauseNow = m_pauseOnNextStatement;
659     pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame);
660
661     DebuggerPausedScope debuggerPausedScope(*this);
662
663     intptr_t sourceID = DebuggerCallFrame::sourceIDForCallFrame(m_currentCallFrame);
664     TextPosition position = DebuggerCallFrame::positionForCallFrame(m_currentCallFrame);
665     pauseNow |= didHitBreakpoint = hasBreakpoint(sourceID, position, &breakpoint);
666     m_lastExecutedLine = position.m_line.zeroBasedInt();
667     if (!pauseNow)
668         return;
669
670     // Make sure we are not going to pause again on breakpoint actions by
671     // reseting the pause state before executing any breakpoint actions.
672     TemporaryPausedState pausedState(*this);
673     m_pauseOnCallFrame = 0;
674     m_pauseOnNextStatement = false;
675
676     if (didHitBreakpoint) {
677         handleBreakpointHit(vmEntryGlobalObject, breakpoint);
678         // Note that the actions can potentially stop the debugger, so we need to check that
679         // we still have a current call frame when we get back.
680         if (breakpoint.autoContinue || !m_currentCallFrame)
681             return;
682         m_pausingBreakpointID = breakpoint.id;
683     }
684
685     {
686         PauseReasonDeclaration reason(*this, didHitBreakpoint ? PausedForBreakpoint : m_reasonForPause);
687         handlePause(vmEntryGlobalObject, m_reasonForPause);
688     }
689
690     m_pausingBreakpointID = noBreakpointID;
691
692     if (!m_pauseOnNextStatement && !m_pauseOnCallFrame) {
693         setSteppingMode(SteppingModeDisabled);
694         m_currentCallFrame = nullptr;
695     }
696 }
697
698 void Debugger::exception(CallFrame* callFrame, JSValue exception, bool hasCatchHandler)
699 {
700     if (m_isPaused)
701         return;
702
703     PauseReasonDeclaration reason(*this, PausedForException);
704     if (m_pauseOnExceptionsState == PauseOnAllExceptions || (m_pauseOnExceptionsState == PauseOnUncaughtExceptions && !hasCatchHandler)) {
705         m_pauseOnNextStatement = true;
706         setSteppingMode(SteppingModeEnabled);
707     }
708
709     m_hasHandlerForExceptionCallback = true;
710     m_currentException = exception;
711     updateCallFrameAndPauseIfNeeded(callFrame);
712     m_currentException = JSValue();
713     m_hasHandlerForExceptionCallback = false;
714 }
715
716 void Debugger::atStatement(CallFrame* callFrame)
717 {
718     if (m_isPaused)
719         return;
720
721     PauseReasonDeclaration reason(*this, PausedAtStatement);
722     updateCallFrameAndPauseIfNeeded(callFrame);
723 }
724
725 void Debugger::callEvent(CallFrame* callFrame)
726 {
727     if (m_isPaused)
728         return;
729
730     PauseReasonDeclaration reason(*this, PausedAfterCall);
731     updateCallFrameAndPauseIfNeeded(callFrame);
732 }
733
734 void Debugger::returnEvent(CallFrame* callFrame)
735 {
736     if (m_isPaused)
737         return;
738
739     PauseReasonDeclaration reason(*this, PausedBeforeReturn);
740     updateCallFrameAndPauseIfNeeded(callFrame);
741
742     // detach may have been called during pauseIfNeeded
743     if (!m_currentCallFrame)
744         return;
745
746     // Treat stepping over a return statement like stepping out.
747     if (m_currentCallFrame == m_pauseOnCallFrame) {
748         VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
749         m_pauseOnCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
750     }
751
752     VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
753     m_currentCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
754 }
755
756 void Debugger::willExecuteProgram(CallFrame* callFrame)
757 {
758     if (m_isPaused)
759         return;
760
761     PauseReasonDeclaration reason(*this, PausedAtStartOfProgram);
762     // FIXME: This check for whether we're debugging a worker thread is a workaround
763     // for https://bugs.webkit.org/show_bug.cgi?id=102637. Remove it when we rework
764     // the debugger implementation to not require callbacks.
765     if (!m_isInWorkerThread)
766         updateCallFrameAndPauseIfNeeded(callFrame);
767     else if (isStepping())
768         updateCallFrame(callFrame);
769 }
770
771 void Debugger::didExecuteProgram(CallFrame* callFrame)
772 {
773     if (m_isPaused)
774         return;
775
776     PauseReasonDeclaration reason(*this, PausedAtEndOfProgram);
777     updateCallFrameAndPauseIfNeeded(callFrame);
778
779     // Treat stepping over the end of a program like stepping out.
780     if (!m_currentCallFrame)
781         return;
782     if (m_currentCallFrame == m_pauseOnCallFrame) {
783         VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
784         m_pauseOnCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
785         if (!m_currentCallFrame)
786             return;
787     }
788     VMEntryFrame* topVMEntryFrame = m_vm->topVMEntryFrame;
789     m_currentCallFrame = m_currentCallFrame->callerFrame(topVMEntryFrame);
790 }
791
792 void Debugger::didReachBreakpoint(CallFrame* callFrame)
793 {
794     if (m_isPaused)
795         return;
796
797     PauseReasonDeclaration reason(*this, PausedForDebuggerStatement);
798     m_pauseOnNextStatement = true;
799     setSteppingMode(SteppingModeEnabled);
800     updateCallFrameAndPauseIfNeeded(callFrame);
801 }
802
803 DebuggerCallFrame* Debugger::currentDebuggerCallFrame() const
804 {
805     ASSERT(m_currentDebuggerCallFrame);
806     return m_currentDebuggerCallFrame.get();
807 }
808
809 } // namespace JSC