From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: deepak1556 <hop2deep@gmail.com>
Date: Thu, 17 Oct 2019 18:00:32 -0700
Subject: feat: add hook to notify script ready from WorkerScriptController

In Off-the-main-thread fetch, the WorkerGlobalScope will be in a half
initialized state until the script is finished downloading.

Doc: https://docs.google.com/document/d/1JCv8TD2nPLNC2iRCp_D1OM4I3uTS0HoEobuTymaMqgw/edit

During this stage if the global object is transformed for ex: copying properties
in DidInitializeWorkerContextOnWorkerThread hook then an access to property like
location will result in a crash WorkerGlobalScope::Url() because the script has
not been set with response URL yet.

This issue cannot happen in chromium with existing usage, but can surface when an
embedder tries to integrate Node.js in the worker. Hence, this new hook is proposed
that clearly establishes the worker script is ready for evaluation with the scope
initialized.

diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 2733fe20a58af97c0fd424bf169254397c631707..d251cba0c8b4a6b7b5aa1fb24488269ef2d162a9 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -397,6 +397,11 @@ class CONTENT_EXPORT ContentRendererClient {
   virtual void DidInitializeWorkerContextOnWorkerThread(
       v8::Local<v8::Context> context) {}
 
+  // Notifies that a worker script has been downloaded, scope initialized and
+  // ready for evaluation. This function is called from the worker thread.
+  virtual void WorkerScriptReadyForEvaluationOnWorkerThread(
+      v8::Local<v8::Context> context) {}
+
   // Notifies that a worker context will be destroyed. This function is called
   // from the worker thread.
   virtual void WillDestroyWorkerContextOnWorkerThread(
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 3bc0313d663b3d948ae00ff5eb7fee6ddf574628..81754497f90b774eb155c84b490f29048bed48a7 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -852,6 +852,12 @@ void RendererBlinkPlatformImpl::WorkerContextCreated(
       worker);
 }
 
+void RendererBlinkPlatformImpl::WorkerScriptReadyForEvaluation(
+    const v8::Local<v8::Context>& worker) {
+  GetContentClient()->renderer()->WorkerScriptReadyForEvaluationOnWorkerThread(
+      worker);
+}
+
 bool RendererBlinkPlatformImpl::AllowScriptExtensionForServiceWorker(
     const blink::WebSecurityOrigin& script_origin) {
   return GetContentClient()->renderer()->AllowScriptExtensionForServiceWorker(
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index 8970240e31bbfbf34433641dcc675f575b86ee09..f89ab57f2976ac917cb936acf392773c1fac6e16 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -188,6 +188,8 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
   void DidStartWorkerThread() override;
   void WillStopWorkerThread() override;
   void WorkerContextCreated(const v8::Local<v8::Context>& worker) override;
+  void WorkerScriptReadyForEvaluation(
+      const v8::Local<v8::Context>& worker) override;
   void WorkerContextWillDestroy(const v8::Local<v8::Context>& worker) override;
   bool AllowScriptExtensionForServiceWorker(
       const blink::WebSecurityOrigin& script_origin) override;
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index f299762e90655ea1a6be4d52257c9ae65598ca98..1f49f4566279c5a2eac0cc3e503d905e3d05a5bd 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -639,6 +639,8 @@ class BLINK_PLATFORM_EXPORT Platform {
   virtual void DidStartWorkerThread() {}
   virtual void WillStopWorkerThread() {}
   virtual void WorkerContextCreated(const v8::Local<v8::Context>& worker) {}
+  virtual void WorkerScriptReadyForEvaluation(
+      const v8::Local<v8::Context>& worker) {}
   virtual void WorkerContextWillDestroy(const v8::Local<v8::Context>& worker) {}
   virtual bool AllowScriptExtensionForServiceWorker(
       const WebSecurityOrigin& script_origin) {
diff --git a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
index 1da03efdb0c935217697372cf222d3025f2214b1..832054db7ad4f52265f2ab649d09b9510627f130 100644
--- a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
+++ b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
@@ -300,6 +300,7 @@ void WorkerOrWorkletScriptController::PrepareForEvaluation() {
   V8PerContextData* per_context_data = script_state_->PerContextData();
   std::ignore =
       per_context_data->ConstructorForType(global_scope_->GetWrapperTypeInfo());
+  Platform::Current()->WorkerScriptReadyForEvaluation(script_state_->GetContext());
   // Inform V8 that origin trial information is now connected with the context,
   // and V8 can extend the context with origin trial features.
   isolate_->InstallConditionalFeatures(script_state_->GetContext());
