@@ -3102,6 +3102,9 @@ class CustomPlatform : public v8::platform::DefaultPlatform {
31023102 : DefaultPlatform(thread_pool_size, idle_task_support),
31033103 context_ (context) {}
31043104
3105+ // SAFETY: The platform is single-owner (via unique_ptr). The destructor
3106+ // runs after all isolates have been disposed and no more task runner
3107+ // callbacks can fire, so DROP does not race with other callbacks.
31053108 ~CustomPlatform () override {
31063109 v8__Platform__CustomPlatform__BASE__DROP (context_);
31073110 }
@@ -3122,6 +3125,9 @@ class CustomPlatform : public v8::platform::DefaultPlatform {
31223125 return custom;
31233126 }
31243127
3128+ // NotifyIsolateShutdown is not virtual on DefaultPlatform, so this
3129+ // hides the base method. This works because callers always go through
3130+ // the CustomPlatform* type (via the platform shared_ptr).
31253131 void NotifyIsolateShutdown (v8::Isolate* isolate) {
31263132 {
31273133 std::lock_guard<std::mutex> lock (mutex_);
@@ -3138,13 +3144,20 @@ class CustomPlatform : public v8::platform::DefaultPlatform {
31383144 DefaultPlatform::NotifyIsolateShutdown (isolate);
31393145 }
31403146
3147+ // Disable thread-isolated allocations (same as UnprotectedDefaultPlatform).
3148+ // Required when isolates may be created on threads other than the one that
3149+ // called v8::V8::Initialize (e.g. worker threads in Deno).
31413150 v8::ThreadIsolatedAllocator* GetThreadIsolatedAllocator () override {
31423151 return nullptr ;
31433152 }
31443153
31453154 private:
31463155 void * context_;
31473156 std::mutex mutex_;
3157+ // weak_ptr so runners are kept alive only while V8 holds a reference.
3158+ // When V8 drops its shared_ptr (e.g. on isolate shutdown), the weak_ptr
3159+ // expires and a fresh wrapper is created if GetForegroundTaskRunner is
3160+ // called again. This avoids preventing cleanup of the underlying runner.
31483161 std::map<std::pair<v8::Isolate*, v8::TaskPriority>,
31493162 std::weak_ptr<CustomTaskRunner>>
31503163 runners_;
0 commit comments