[Code Health] Clean up gin function templates on isolate disposal

gin previously relied exclusively on garbage collection in order to
trigger cleanup of function templates. This is unreliable as garbage
collection is never guaranteed to run, especially for short-lived
isolates.

This change adds observers for isolate disposal in order to clean up
function templates once an isolate is disposed.

A few (possibly non-exhaustive) leaked dangling pointers are fixed
with this change.

Bug: 1462087
AX-Relnotes: n/a
Change-Id: I2462de9cfb9622c03bc047b4cd727c6bf3cd3b11
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5104930
Commit-Queue: Ashley Newson <[email protected]>
Reviewed-by: Katie Dektar <[email protected]>
Reviewed-by: Michael Lippautz <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1244593}
diff --git a/gin/per_isolate_data.h b/gin/per_isolate_data.h
index 6353521..3d3f07c 100644
--- a/gin/per_isolate_data.h
+++ b/gin/per_isolate_data.h
@@ -8,8 +8,10 @@
 #include <map>
 #include <memory>
 
+#include "base/check.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
 #include "base/task/single_thread_task_runner.h"
 #include "gin/gin_export.h"
 #include "gin/public/isolate_holder.h"
@@ -29,6 +31,16 @@
 // class stores all the Gin-related data that varies per isolate.
 class GIN_EXPORT PerIsolateData {
  public:
+  class DisposeObserver : public base::CheckedObserver {
+   public:
+    // Called just before the isolate is about to be disposed. The isolate will
+    // be entered before the observer is notified, but there will not be a
+    // handle scope by default.
+    virtual void OnBeforeDispose(v8::Isolate* isolate) = 0;
+    // Called just after the isolate has been disposed.
+    virtual void OnDisposed() = 0;
+  };
+
   PerIsolateData(
       v8::Isolate* isolate,
       v8::ArrayBuffer::Allocator* allocator,
@@ -72,6 +84,11 @@
       WrappableBase* base);
   NamedPropertyInterceptor* GetNamedPropertyInterceptor(WrappableBase* base);
 
+  void AddDisposeObserver(DisposeObserver* observer);
+  void RemoveDisposeObserver(DisposeObserver* observer);
+  void NotifyBeforeDispose();
+  void NotifyDisposed();
+
   void EnableIdleTasks(std::unique_ptr<V8IdleTaskRunner> idle_task_runner);
 
   v8::Isolate* isolate() { return isolate_; }
@@ -99,6 +116,7 @@
   FunctionTemplateMap function_templates_;
   IndexedPropertyInterceptorMap indexed_interceptors_;
   NamedPropertyInterceptorMap named_interceptors_;
+  base::ObserverList<DisposeObserver> dispose_observers_;
   std::shared_ptr<V8ForegroundTaskRunnerBase> task_runner_;
   std::shared_ptr<V8ForegroundTaskRunnerBase> low_priority_task_runner_;
 };