void DOMTimer::fired() { ExecutionContext* context = getExecutionContext(); ASSERT(context); context->timers()->setTimerNestingLevel(m_nestingLevel); ASSERT(!context->activeDOMObjectsAreSuspended()); // Only the first execution of a multi-shot timer should get an affirmative user gesture indicator. UserGestureIndicator gestureIndicator(m_userGestureToken.release()); TRACE_EVENT1("devtools.timeline", "TimerFire", "data", InspectorTimerFireEvent::data(context, m_timeoutID)); InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireTimer(context, m_timeoutID); // Simple case for non-one-shot timers. if (isActive()) { if (repeatInterval() && repeatInterval() < minimumInterval) { m_nestingLevel++; if (m_nestingLevel >= maxTimerNestingLevel) augmentRepeatInterval(minimumInterval - repeatInterval()); } // No access to member variables after this point, it can delete the timer. m_action->execute(context); InspectorInstrumentation::didFireTimer(cookie); return; } RawPtr<DOMTimer> protect(this); // Unregister the timer from ExecutionContext before executing the action // for one-shot timers. RawPtr<ScheduledAction> action = m_action.release(); context->timers()->removeTimeoutByID(m_timeoutID); action->execute(context); InspectorInstrumentation::didFireTimer(cookie); TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data()); // ExecutionContext might be already gone when we executed action->execute(). if (getExecutionContext()) getExecutionContext()->timers()->setTimerNestingLevel(0); }