RefPtr<JSC::Profile> InspectorTimelineAgent::stopFromConsole(JSC::ExecState* exec, const String& title)
{
    // Stop profiles in reverse order. If the title is empty, then stop the last profile.
    // Otherwise, match the title of the profile to stop.
    for (ptrdiff_t i = m_pendingConsoleProfileRecords.size() - 1; i >= 0; --i) {
        const TimelineRecordEntry& record = m_pendingConsoleProfileRecords[i];

        String recordTitle;
        record.data->getString(ASCIILiteral("title"), recordTitle);

        if (title.isEmpty() || recordTitle == title) {
            RefPtr<JSC::Profile> profile = stopProfiling(exec, title);
            if (profile)
                TimelineRecordFactory::appendProfile(record.data.get(), profile.copyRef());

            didCompleteRecordEntry(record);

            m_pendingConsoleProfileRecords.remove(i);

            if (!m_enabledFromFrontend && m_pendingConsoleProfileRecords.isEmpty())
                internalStop();

            return WTF::move(profile);
        }
    }

    return nullptr;
}
void InspectorTimelineAgent::didCompleteCurrentRecord(TimelineRecordType type)
{
    // An empty stack could merely mean that the timeline agent was turned on in the middle of
    // an event.  Don't treat as an error.
    if (!m_recordStack.isEmpty()) {
        TimelineRecordEntry entry = m_recordStack.last();
        m_recordStack.removeLast();
        ASSERT_UNUSED(type, entry.type == type);
        didCompleteRecordEntry(entry);
    }
}
void InspectorTimelineAgent::didCompleteCurrentRecord(TimelineRecordType type)
{
    // An empty stack could merely mean that the timeline agent was turned on in the middle of
    // an event.  Don't treat as an error.
    if (!m_recordStack.isEmpty()) {
        TimelineRecordEntry entry = m_recordStack.last();
        m_recordStack.removeLast();
        ASSERT_UNUSED(type, entry.type == type);

        // Don't send RenderingFrame records that have no children to reduce noise.
        if (entry.type == TimelineRecordType::RenderingFrame && !entry.children->length())
            return;

        didCompleteRecordEntry(entry);
    }
}
void InspectorTimelineAgent::stop(ErrorString&) {
    if (!m_enabled)
        return;

    RefPtr<JSC::Profile> profile = stopProfiling(m_globalObject.globalExec(), WTF::emptyString());
    if (profile)
        TimelineRecordFactory::appendProfile(m_consoleRecordEntry.data.get(), profile.copyRef());

    didCompleteRecordEntry(m_consoleRecordEntry);

    auto stopwatch = m_globalObject.inspectorController().executionStopwatch();
    if (stopwatch->isActive())
        stopwatch->stop();

    m_enabled = false;

    if (m_frontendDispatcher)
        m_frontendDispatcher->recordingStopped(timestamp());
}