Add JSBasedEventListener::GetSourceLocation()

This CL adds JSBasedEventListener::GetSourceLocation().
JSEventHandlerForContentAttribute can provide its SourceLocation even
if it cannot get compiled, so it overrides this method.

Bug: 872138
Change-Id: I8d575f3e847d37b7eb202833971fb610c589dd8f
Reviewed-on: https://chromium-review.googlesource.com/c/1253317
Commit-Queue: Yuki Yamada <yukiy@google.com>
Reviewed-by: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: Hitoshi Yoshida <peria@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Hayato Ito <hayato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#597837}
diff --git a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc
index 210723f..d7613f3 100644
--- a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc
+++ b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h"
 
+#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/document_parser.h"
@@ -152,4 +153,13 @@
     event_symbol.Set(global, current_event);
 }
 
+std::unique_ptr<SourceLocation> JSBasedEventListener::GetSourceLocation(
+    EventTarget& target) {
+  v8::HandleScope(GetIsolate());
+  v8::Local<v8::Value> effective_function = GetEffectiveFunction(target);
+  if (effective_function->IsFunction())
+    return SourceLocation::FromFunction(effective_function.As<v8::Function>());
+  return nullptr;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h
index 060272b..270d5b4f 100644
--- a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h
+++ b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h
@@ -14,6 +14,7 @@
 class DOMWrapperWorld;
 class Event;
 class EventTarget;
+class SourceLocation;
 
 // |JSBasedEventListener| is the base class for JS-based event listeners,
 // i.e. EventListener and EventHandler in the standards.
@@ -67,6 +68,8 @@
   // Only DevTools is allowed to use this method.
   DOMWrapperWorld& GetWorldForInspector() const { return GetWorld(); }
 
+  virtual std::unique_ptr<SourceLocation> GetSourceLocation(EventTarget&);
+
  protected:
   explicit JSBasedEventListener(ListenerType);
   virtual v8::Isolate* GetIsolate() const = 0;
diff --git a/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.cc b/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.cc
index ff8fa50d..de79b9b 100644
--- a/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.cc
+++ b/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h"
 
+#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/dom/events/event_target.h"
 #include "third_party/blink/renderer/core/events/error_event.h"
@@ -194,4 +195,15 @@
   return JSEventHandler::GetListenerObject(event_target);
 }
 
+std::unique_ptr<SourceLocation>
+JSEventHandlerForContentAttribute::GetSourceLocation(EventTarget& target) {
+  v8::HandleScope(GetIsolate());
+  auto source_location = JSEventHandler::GetSourceLocation(target);
+  if (source_location)
+    return source_location;
+  // Fallback to uncompiled source info.
+  return SourceLocation::Create(source_url_, position_.line_.ZeroBasedInt(),
+                                position_.column_.ZeroBasedInt(), nullptr);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h b/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h
index 816b0fb..86b6a3bf 100644
--- a/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h
+++ b/third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h
@@ -32,6 +32,7 @@
 
   // blink::JSBasedEventListener overrides:
   v8::Local<v8::Value> GetListenerObject(EventTarget&) override;
+  std::unique_ptr<SourceLocation> GetSourceLocation(EventTarget&) override;
 
   const String& Code() const override { return code_; }
 
diff --git a/third_party/blink/renderer/core/dom/events/event_target.cc b/third_party/blink/renderer/core/dom/events/event_target.cc
index 1f6e213e..a8f3eb9 100644
--- a/third_party/blink/renderer/core/dom/events/event_target.cc
+++ b/third_party/blink/renderer/core/dom/events/event_target.cc
@@ -137,22 +137,9 @@
       "Consider marking event handler as 'passive' to make the page more "
       "responsive.",
       event.type().GetString().Utf8().data(), delayed.InMilliseconds());
-
-  {
-    v8::Isolate* isolate = ToIsolate(target.GetExecutionContext());
-    v8::HandleScope handle_scope(isolate);
-
-    // TODO(yukiy): create a method that returns SourceLocation of effective
-    // function in JSBasedEventListener.
-    v8::Local<v8::Value> handler = listener->GetEffectiveFunction(target);
-    PerformanceMonitor::ReportGenericViolation(
-        target.GetExecutionContext(), PerformanceMonitor::kBlockedEvent,
-        message_text, delayed,
-        handler->IsFunction()
-            ? SourceLocation::FromFunction(handler.As<v8::Function>())
-            : nullptr);
-  }
-
+  PerformanceMonitor::ReportGenericViolation(
+      target.GetExecutionContext(), PerformanceMonitor::kBlockedEvent,
+      message_text, delayed, listener->GetSourceLocation(target));
   registered_listener->SetBlockedEventWarningEmitted();
 }