Web Inspector: Timelines: correctly label Intersection Observer callbacks
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Dec 2018 23:17:31 +0000 (23:17 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Dec 2018 23:17:31 +0000 (23:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192669
<rdar://problem/46702490>

Reviewed by Joseph Pecoraro.

Add InspectorInstrumentation::willFireObserverCallback() and use it to wrap calls
to Intersection Observer, Performance Observer and Mutation Observer callbacks so
that they get correctly labeled in the Inspector timeline.

Source/JavaScriptCore:

* inspector/protocol/Timeline.json:

Source/WebCore:

* dom/MutationObserver.cpp:
(WebCore::MutationObserver::deliver):
* en.lproj/Localizable.strings:
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::willFireObserverCallbackImpl):
(WebCore::InspectorInstrumentation::didFireObserverCallbackImpl):
* inspector/InspectorInstrumentation.h:
(WebCore::InspectorInstrumentation::willFireObserverCallback):
(WebCore::InspectorInstrumentation::didFireObserverCallback):
* inspector/TimelineRecordFactory.cpp:
(WebCore::TimelineRecordFactory::createObserverCallbackData):
* inspector/TimelineRecordFactory.h:
* inspector/agents/InspectorTimelineAgent.cpp:
(WebCore::InspectorTimelineAgent::willFireObserverCallback):
(WebCore::InspectorTimelineAgent::didFireObserverCallback):
(WebCore::toProtocol):
* inspector/agents/InspectorTimelineAgent.h:
* page/IntersectionObserver.cpp:
(WebCore::IntersectionObserver::notify):
* page/PerformanceObserver.cpp:
(WebCore::PerformanceObserver::deliver):

Source/WebInspectorUI:

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Controllers/TimelineManager.js:
(WI.TimelineManager.prototype._processRecord):
* UserInterface/Models/ScriptTimelineRecord.js:
(WI.ScriptTimelineRecord.EventType.displayName):
* UserInterface/Views/TimelineTabContentView.js:
(WI.TimelineTabContentView.iconClassNameForRecord):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239397 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/protocol/Timeline.json
Source/WebCore/ChangeLog
Source/WebCore/dom/MutationObserver.cpp
Source/WebCore/en.lproj/Localizable.strings
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/TimelineRecordFactory.cpp
Source/WebCore/inspector/TimelineRecordFactory.h
Source/WebCore/inspector/agents/InspectorTimelineAgent.cpp
Source/WebCore/inspector/agents/InspectorTimelineAgent.h
Source/WebCore/page/IntersectionObserver.cpp
Source/WebCore/page/PerformanceObserver.cpp
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js
Source/WebInspectorUI/UserInterface/Models/ScriptTimelineRecord.js
Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js

index 8227173..6619070 100644 (file)
@@ -1,3 +1,17 @@
+2018-12-18  Simon Fraser  <simon.fraser@apple.com>
+
+        Web Inspector: Timelines: correctly label Intersection Observer callbacks
+        https://bugs.webkit.org/show_bug.cgi?id=192669
+        <rdar://problem/46702490>
+
+        Reviewed by Joseph Pecoraro.
+
+        Add InspectorInstrumentation::willFireObserverCallback() and use it to wrap calls
+        to Intersection Observer, Performance Observer and Mutation Observer callbacks so 
+        that they get correctly labeled in the Inspector timeline.
+
+        * inspector/protocol/Timeline.json:
+
 2018-12-18  Mark Lam  <mark.lam@apple.com>
 
         JSPropertyNameEnumerator should cache the iterated object's structure only after getting its property names.
index 4a8ad6d..6b55c29 100644 (file)
@@ -28,7 +28,8 @@
                 "ConsoleProfile",
                 "RequestAnimationFrame",
                 "CancelAnimationFrame",
-                "FireAnimationFrame"
+                "FireAnimationFrame",
+                "ObserverCallback"
             ]
         },
         {
index daaf309..6f43af6 100644 (file)
@@ -1,3 +1,37 @@
+2018-12-18  Simon Fraser  <simon.fraser@apple.com>
+
+        Web Inspector: Timelines: correctly label Intersection Observer callbacks
+        https://bugs.webkit.org/show_bug.cgi?id=192669
+        <rdar://problem/46702490>
+
+        Reviewed by Joseph Pecoraro.
+
+        Add InspectorInstrumentation::willFireObserverCallback() and use it to wrap calls
+        to Intersection Observer, Performance Observer and Mutation Observer callbacks so 
+        that they get correctly labeled in the Inspector timeline.
+
+        * dom/MutationObserver.cpp:
+        (WebCore::MutationObserver::deliver):
+        * en.lproj/Localizable.strings:
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::willFireObserverCallbackImpl):
+        (WebCore::InspectorInstrumentation::didFireObserverCallbackImpl):
+        * inspector/InspectorInstrumentation.h:
+        (WebCore::InspectorInstrumentation::willFireObserverCallback):
+        (WebCore::InspectorInstrumentation::didFireObserverCallback):
+        * inspector/TimelineRecordFactory.cpp:
+        (WebCore::TimelineRecordFactory::createObserverCallbackData):
+        * inspector/TimelineRecordFactory.h:
+        * inspector/agents/InspectorTimelineAgent.cpp:
+        (WebCore::InspectorTimelineAgent::willFireObserverCallback):
+        (WebCore::InspectorTimelineAgent::didFireObserverCallback):
+        (WebCore::toProtocol):
+        * inspector/agents/InspectorTimelineAgent.h:
+        * page/IntersectionObserver.cpp:
+        (WebCore::IntersectionObserver::notify):
+        * page/PerformanceObserver.cpp:
+        (WebCore::PerformanceObserver::deliver):
+
 2018-12-19  Claudio Saavedra  <csaavedra@igalia.com>
 
         ContentExtensions: DFANode.cpp:66:44: error: narrowing conversion of '-1' from 'int' to 'char' inside { }
index 10486ae..8462495 100644 (file)
@@ -36,6 +36,7 @@
 #include "Document.h"
 #include "GCReachableRef.h"
 #include "HTMLSlotElement.h"
+#include "InspectorInstrumentation.h"
 #include "Microtasks.h"
 #include "MutationCallback.h"
 #include "MutationObserverRegistration.h"
@@ -244,8 +245,15 @@ void MutationObserver::deliver()
     records.swap(m_records);
 
     // FIXME: Keep mutation observer callback as long as its observed nodes are alive. See https://webkit.org/b/179224.
-    if (m_callback->hasCallback())
+    if (m_callback->hasCallback()) {
+        auto* context = m_callback->scriptExecutionContext();
+        if (!context)
+            return;
+
+        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireObserverCallback(*context, "MutationObserver"_s);
         m_callback->handleEvent(*this, records, *this);
+        InspectorInstrumentation::didFireObserverCallback(cookie);
+    }
 }
 
 void MutationObserver::notifyMutationObservers()
index 553e562..e3490d6 100644 (file)
 /* Show Media Controls context menu item */
 "Show Controls" = "Show Controls";
 
+/* Action from safe browsing warning */
+"Show Details" = "Show Details";
+
 /* Show fonts context menu item */
 "Show Fonts" = "Show Fonts";
 
 /* menu item title */
 "Show Substitutions" = "Show Substitutions";
 
-/* Action from safe browsing warning */
-"Show Details" = "Show Details";
-
 /* Title of the context menu item to show when PDFPlugin was used instead of a blocked plugin */
 "Show in blocked plug-in" = "Show in blocked plug-in";
 
index 59a8b08..62e09cf 100644 (file)
@@ -1099,6 +1099,22 @@ void InspectorInstrumentation::didFireAnimationFrameImpl(const InspectorInstrume
         timelineAgent->didFireAnimationFrame();
 }
 
+InspectorInstrumentationCookie InspectorInstrumentation::willFireObserverCallbackImpl(InstrumentingAgents& instrumentingAgents, const String& callbackType, ScriptExecutionContext& context)
+{
+    int timelineAgentId = 0;
+    if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent()) {
+        timelineAgent->willFireObserverCallback(callbackType, frameForScriptExecutionContext(&context));
+        timelineAgentId = timelineAgent->id();
+    }
+    return InspectorInstrumentationCookie(instrumentingAgents, timelineAgentId);
+}
+
+void InspectorInstrumentation::didFireObserverCallbackImpl(const InspectorInstrumentationCookie& cookie)
+{
+    if (InspectorTimelineAgent* timelineAgent = retrieveTimelineAgent(cookie))
+        timelineAgent->didFireObserverCallback();
+}
+
 void InspectorInstrumentation::registerInstrumentingAgents(InstrumentingAgents& instrumentingAgents)
 {
     if (!s_instrumentingAgentsSet)
index b9a42e6..6b20cca 100644 (file)
@@ -235,6 +235,9 @@ public:
     static InspectorInstrumentationCookie willFireAnimationFrame(Document&, int callbackId);
     static void didFireAnimationFrame(const InspectorInstrumentationCookie&);
 
+    static InspectorInstrumentationCookie willFireObserverCallback(ScriptExecutionContext&, const String& callbackType);
+    static void didFireObserverCallback(const InspectorInstrumentationCookie&);
+
     static void didOpenDatabase(ScriptExecutionContext*, RefPtr<Database>&&, const String& domain, const String& name, const String& version);
 
     static void didDispatchDOMStorageEvent(Page&, const String& key, const String& oldValue, const String& newValue, StorageType, SecurityOrigin*);
@@ -407,6 +410,9 @@ private:
     static InspectorInstrumentationCookie willFireAnimationFrameImpl(InstrumentingAgents&, int callbackId, Document&);
     static void didFireAnimationFrameImpl(const InspectorInstrumentationCookie&);
 
+    static InspectorInstrumentationCookie willFireObserverCallbackImpl(InstrumentingAgents&, const String&, ScriptExecutionContext&);
+    static void didFireObserverCallbackImpl(const InspectorInstrumentationCookie&);
+
     static void didOpenDatabaseImpl(InstrumentingAgents&, RefPtr<Database>&&, const String& domain, const String& name, const String& version);
 
     static void didDispatchDOMStorageEventImpl(InstrumentingAgents&, const String& key, const String& oldValue, const String& newValue, StorageType, SecurityOrigin*);
@@ -1410,6 +1416,7 @@ inline void InspectorInstrumentation::didCancelAnimationFrame(Document& document
 
 inline InspectorInstrumentationCookie InspectorInstrumentation::willFireAnimationFrame(Document& document, int callbackId)
 {
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
     if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
         return willFireAnimationFrameImpl(*instrumentingAgents, callbackId, document);
     return InspectorInstrumentationCookie();
@@ -1422,6 +1429,21 @@ inline void InspectorInstrumentation::didFireAnimationFrame(const InspectorInstr
         didFireAnimationFrameImpl(cookie);
 }
 
+inline InspectorInstrumentationCookie InspectorInstrumentation::willFireObserverCallback(ScriptExecutionContext& context, const String& callbackType)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(InspectorInstrumentationCookie());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        return willFireObserverCallbackImpl(*instrumentingAgents, callbackType, context);
+    return InspectorInstrumentationCookie();
+}
+
+inline void InspectorInstrumentation::didFireObserverCallback(const InspectorInstrumentationCookie& cookie)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (cookie.isValid())
+        didFireObserverCallbackImpl(cookie);
+}
+
 inline void InspectorInstrumentation::layerTreeDidChange(Page* page)
 {
     FAST_RETURN_IF_NO_FRONTENDS(void());
index f2b7be1..0cab454 100644 (file)
@@ -125,6 +125,13 @@ Ref<JSON::Object> TimelineRecordFactory::createAnimationFrameData(int callbackId
     return data;
 }
 
+Ref<JSON::Object> TimelineRecordFactory::createObserverCallbackData(const String& callbackType)
+{
+    Ref<JSON::Object> data = JSON::Object::create();
+    data->setString("type"_s, callbackType);
+    return data;
+}
+
 static Ref<JSON::Array> createQuad(const FloatQuad& quad)
 {
     Ref<JSON::Array> array = JSON::Array::create();
index ab98212..d5c13ff 100644 (file)
@@ -58,6 +58,7 @@ public:
     static Ref<JSON::Object> createEvaluateScriptData(const String&, double lineNumber);
     static Ref<JSON::Object> createTimeStampData(const String&);
     static Ref<JSON::Object> createAnimationFrameData(int callbackId);
+    static Ref<JSON::Object> createObserverCallbackData(const String& callbackType);
     static Ref<JSON::Object> createPaintData(const FloatQuad&);
 
     static void appendLayoutRoot(JSON::Object* data, const FloatQuad&);
index 9732ec0..db70295 100644 (file)
@@ -597,6 +597,16 @@ void InspectorTimelineAgent::didFireAnimationFrame()
     didCompleteCurrentRecord(TimelineRecordType::FireAnimationFrame);
 }
 
+void InspectorTimelineAgent::willFireObserverCallback(const String& callbackType, Frame* frame)
+{
+    pushCurrentRecord(TimelineRecordFactory::createObserverCallbackData(callbackType), TimelineRecordType::ObserverCallback, false, frame);
+}
+
+void InspectorTimelineAgent::didFireObserverCallback()
+{
+    didCompleteCurrentRecord(TimelineRecordType::ObserverCallback);
+}
+
 // ScriptDebugListener
 
 void InspectorTimelineAgent::breakpointActionProbe(JSC::ExecState& state, const Inspector::ScriptBreakpointAction& action, unsigned /*batchId*/, unsigned sampleId, JSC::JSValue)
@@ -654,6 +664,9 @@ static Inspector::Protocol::Timeline::EventType toProtocol(TimelineRecordType ty
         return Inspector::Protocol::Timeline::EventType::CancelAnimationFrame;
     case TimelineRecordType::FireAnimationFrame:
         return Inspector::Protocol::Timeline::EventType::FireAnimationFrame;
+
+    case TimelineRecordType::ObserverCallback:
+        return Inspector::Protocol::Timeline::EventType::ObserverCallback;
     }
 
     return Inspector::Protocol::Timeline::EventType::TimeStamp;
index d2616db..cf2635e 100644 (file)
@@ -83,6 +83,8 @@ enum class TimelineRecordType {
     RequestAnimationFrame,
     CancelAnimationFrame,
     FireAnimationFrame,
+    
+    ObserverCallback,
 };
 
 class InspectorTimelineAgent final
@@ -137,6 +139,8 @@ public:
     void didCancelAnimationFrame(int callbackId, Frame*);
     void willFireAnimationFrame(int callbackId, Frame*);
     void didFireAnimationFrame();
+    void willFireObserverCallback(const String& callbackType, Frame*);
+    void didFireObserverCallback();
     void time(Frame&, const String&);
     void timeEnd(Frame&, const String&);
     void mainFrameStartedLoading();
index 0b4ef28..87d0548 100644 (file)
@@ -32,6 +32,7 @@
 #include "CSSPropertyParserHelpers.h"
 #include "CSSTokenizer.h"
 #include "Element.h"
+#include "InspectorInstrumentation.h"
 #include "IntersectionObserverCallback.h"
 #include "IntersectionObserverEntry.h"
 #include "Performance.h"
@@ -256,8 +257,16 @@ void IntersectionObserver::notify()
         return;
     }
 
+    auto* context = m_callback->scriptExecutionContext();
+    if (!context)
+        return;
+
+    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireObserverCallback(*context, "IntersectionObserver"_s);
+
     auto takenRecords = takeRecords();
     m_callback->handleEvent(WTFMove(takenRecords.records), *this);
+
+    InspectorInstrumentation::didFireObserverCallback(cookie);
 }
 
 bool IntersectionObserver::hasPendingActivity() const
index 11e5949..4a3c9ff 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "DOMWindow.h"
 #include "Document.h"
+#include "InspectorInstrumentation.h"
 #include "Performance.h"
 #include "PerformanceObserverEntryList.h"
 #include "WorkerGlobalScope.h"
@@ -100,9 +101,16 @@ void PerformanceObserver::deliver()
     if (m_entriesToDeliver.isEmpty())
         return;
 
+    auto* context = m_callback->scriptExecutionContext();
+    if (!context)
+        return;
+
     Vector<RefPtr<PerformanceEntry>> entries = WTFMove(m_entriesToDeliver);
     auto list = PerformanceObserverEntryList::create(WTFMove(entries));
+
+    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireObserverCallback(*context, "PerformanceObserver"_s);
     m_callback->handleEvent(list, *this);
+    InspectorInstrumentation::didFireObserverCallback(cookie);
 }
 
 } // namespace WebCore
index a538863..90f487b 100644 (file)
@@ -1,3 +1,23 @@
+2018-12-18  Simon Fraser  <simon.fraser@apple.com>
+
+        Web Inspector: Timelines: correctly label Intersection Observer callbacks
+        https://bugs.webkit.org/show_bug.cgi?id=192669
+        <rdar://problem/46702490>
+
+        Reviewed by Joseph Pecoraro.
+
+        Add InspectorInstrumentation::willFireObserverCallback() and use it to wrap calls
+        to Intersection Observer, Performance Observer and Mutation Observer callbacks so 
+        that they get correctly labeled in the Inspector timeline.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Controllers/TimelineManager.js:
+        (WI.TimelineManager.prototype._processRecord):
+        * UserInterface/Models/ScriptTimelineRecord.js:
+        (WI.ScriptTimelineRecord.EventType.displayName):
+        * UserInterface/Views/TimelineTabContentView.js:
+        (WI.TimelineTabContentView.iconClassNameForRecord):
+
 2018-12-19  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: Audit: "Clear Filters" button gets clipped when window is vertically small
index 60fc1d9..619824e 100644 (file)
@@ -45,6 +45,7 @@ localizedStrings["%s (%s)"] = "%s (%s)";
 localizedStrings["%s (%s, %s)"] = "%s (%s, %s)";
 localizedStrings["%s (default)"] = "%s (default)";
 localizedStrings["%s (hidden)"] = "%s (hidden)";
+localizedStrings["%s Callback"] = "%s Callback";
 localizedStrings["%s Event Dispatched"] = "%s Event Dispatched";
 localizedStrings["%s Fired"] = "%s Fired";
 localizedStrings["%s Prototype"] = "%s Prototype";
@@ -53,6 +54,7 @@ localizedStrings["%s \u2013 %s"] = "%s \u2013 %s";
 localizedStrings["%s \u2014 %s"] = "%s \u2014 %s";
 localizedStrings["%s cannot be modified"] = "%s cannot be modified";
 localizedStrings["%s delay"] = "%s delay";
+localizedStrings["%s eval\n%s async"] = "%s eval\n%s async";
 localizedStrings["%s interval"] = "%s interval";
 localizedStrings["(Action %s)"] = "(Action %s)";
 localizedStrings["(Disk)"] = "(Disk)";
@@ -121,6 +123,7 @@ localizedStrings["Assertion Failed: %s"] = "Assertion Failed: %s";
 localizedStrings["Assertion Failures"] = "Assertion Failures";
 localizedStrings["Assertion with message: %s"] = "Assertion with message: %s";
 localizedStrings["Assertive"] = "Assertive";
+localizedStrings["Async audits are not supported."] = "Async audits are not supported.";
 localizedStrings["Attribute"] = "Attribute";
 localizedStrings["Attribute Modified"] = "Attribute Modified";
 localizedStrings["Attributes"] = "Attributes";
@@ -630,6 +633,7 @@ localizedStrings["None"] = "None";
 localizedStrings["Not found"] = "Not found";
 localizedStrings["Object Graph"] = "Object Graph";
 localizedStrings["Object Store"] = "Object Store";
+localizedStrings["Observer Callback"] = "Observer Callback";
 localizedStrings["Off"] = "Off";
 localizedStrings["Once"] = "Once";
 localizedStrings["Online"] = "Online";
index a9867aa..a254f00 100644 (file)
@@ -546,6 +546,12 @@ WI.TimelineManager = class TimelineManager extends WI.Object
             case TimelineAgent.EventType.TimerFire:
                 record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.TimerFired, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.timerId, profileData);
                 break;
+            case TimelineAgent.EventType.ObserverCallback:
+                record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.ObserverCallback, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.type, profileData);
+                break;
+            case TimelineAgent.EventType.FireAnimationFrame:
+                record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.AnimationFrameFired, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.id, profileData);
+                break;
             default:
                 record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.ScriptEvaluated, startTime, endTime, callFrames, sourceCodeLocation, null, profileData);
                 break;
@@ -563,7 +569,8 @@ WI.TimelineManager = class TimelineManager extends WI.Object
         case TimelineAgent.EventType.TimerFire:
         case TimelineAgent.EventType.EventDispatch:
         case TimelineAgent.EventType.FireAnimationFrame:
-            // These are handled when the parent of FunctionCall or EvaluateScript.
+        case TimelineAgent.EventType.ObserverCallback:
+            // These are handled when we see the child FunctionCall or EvaluateScript.
             break;
 
         case TimelineAgent.EventType.FunctionCall:
@@ -596,6 +603,9 @@ WI.TimelineManager = class TimelineManager extends WI.Object
             case TimelineAgent.EventType.EventDispatch:
                 record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.EventDispatched, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.type, profileData);
                 break;
+            case TimelineAgent.EventType.ObserverCallback:
+                record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.ObserverCallback, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.type, profileData);
+                break;
             case TimelineAgent.EventType.FireAnimationFrame:
                 record = new WI.ScriptTimelineRecord(WI.ScriptTimelineRecord.EventType.AnimationFrameFired, startTime, endTime, callFrames, sourceCodeLocation, parentRecordPayload.data.id, profileData);
                 break;
index 331bdd5..5f59b0d 100644 (file)
@@ -194,6 +194,7 @@ WI.ScriptTimelineRecord.EventType = {
     AnimationFrameFired: "script-timeline-record-animation-frame-fired",
     AnimationFrameRequested: "script-timeline-record-animation-frame-requested",
     AnimationFrameCanceled: "script-timeline-record-animation-frame-canceled",
+    ObserverCallback: "script-timeline-record-observer-callback",
     ConsoleProfileRecorded: "script-timeline-record-console-profile-recorded",
     GarbageCollected: "script-timeline-record-garbage-collected",
 };
@@ -400,6 +401,10 @@ WI.ScriptTimelineRecord.EventType.displayName = function(eventType, details, inc
         if (details && includeDetailsInMainTitle)
             return WI.UIString("Animation Frame %d Fired").format(details);
         return WI.UIString("Animation Frame Fired");
+    case WI.ScriptTimelineRecord.EventType.ObserverCallback:
+        if (details && (details instanceof String || typeof details === "string"))
+            return WI.UIString("%s Callback").format(details);
+        return WI.UIString("Observer Callback");
     case WI.ScriptTimelineRecord.EventType.AnimationFrameRequested:
         if (details && includeDetailsInMainTitle)
             return WI.UIString("Animation Frame %d Requested").format(details);
index 5b57d80..c0adfb6 100644 (file)
@@ -207,6 +207,7 @@ WI.TimelineTabContentView = class TimelineTabContentView extends WI.ContentBrows
                 return WI.TimelineRecordTreeElement.EvaluatedRecordIconStyleClass;
             case WI.ScriptTimelineRecord.EventType.MicrotaskDispatched:
             case WI.ScriptTimelineRecord.EventType.EventDispatched:
+            case WI.ScriptTimelineRecord.EventType.ObserverCallback:
                 return WI.TimelineRecordTreeElement.EventRecordIconStyleClass;
             case WI.ScriptTimelineRecord.EventType.ProbeSampleRecorded:
                 return WI.TimelineRecordTreeElement.ProbeRecordIconStyleClass;