1 // Copyright 2021 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef INCLUDE_V8_MICROTASKS_QUEUE_H_ 6 #define INCLUDE_V8_MICROTASKS_QUEUE_H_ 7 8 #include <stddef.h> 9 10 #include <memory> 11 12 #include "v8-local-handle.h" // NOLINT(build/include_directory) 13 #include "v8-microtask.h" // NOLINT(build/include_directory) 14 #include "v8config.h" // NOLINT(build/include_directory) 15 16 namespace v8 { 17 18 class Function; 19 20 namespace internal { 21 class Isolate; 22 class MicrotaskQueue; 23 } // namespace internal 24 25 /** 26 * Represents the microtask queue, where microtasks are stored and processed. 27 * https://html.spec.whatwg.org/multipage/webappapis.html#microtask-queue 28 * https://html.spec.whatwg.org/multipage/webappapis.html#enqueuejob(queuename,-job,-arguments) 29 * https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint 30 * 31 * A MicrotaskQueue instance may be associated to multiple Contexts by passing 32 * it to Context::New(), and they can be detached by Context::DetachGlobal(). 33 * The embedder must keep the MicrotaskQueue instance alive until all associated 34 * Contexts are gone or detached. 35 * 36 * Use the same instance of MicrotaskQueue for all Contexts that may access each 37 * other synchronously. E.g. for Web embedding, use the same instance for all 38 * origins that share the same URL scheme and eTLD+1. 39 */ 40 class V8_EXPORT MicrotaskQueue { 41 public: 42 /** 43 * Creates an empty MicrotaskQueue instance. 44 */ 45 static std::unique_ptr<MicrotaskQueue> New( 46 Isolate* isolate, MicrotasksPolicy policy = MicrotasksPolicy::kAuto); 47 48 virtual ~MicrotaskQueue() = default; 49 50 /** 51 * Enqueues the callback to the queue. 52 */ 53 virtual void EnqueueMicrotask(Isolate* isolate, 54 Local<Function> microtask) = 0; 55 56 /** 57 * Enqueues the callback to the queue. 58 */ 59 virtual void EnqueueMicrotask(v8::Isolate* isolate, 60 MicrotaskCallback callback, 61 void* data = nullptr) = 0; 62 63 /** 64 * Adds a callback to notify the embedder after microtasks were run. The 65 * callback is triggered by explicit RunMicrotasks call or automatic 66 * microtasks execution (see Isolate::SetMicrotasksPolicy). 67 * 68 * Callback will trigger even if microtasks were attempted to run, 69 * but the microtasks queue was empty and no single microtask was actually 70 * executed. 71 * 72 * Executing scripts inside the callback will not re-trigger microtasks and 73 * the callback. 74 */ 75 virtual void AddMicrotasksCompletedCallback( 76 MicrotasksCompletedCallbackWithData callback, void* data = nullptr) = 0; 77 78 /** 79 * Removes callback that was installed by AddMicrotasksCompletedCallback. 80 */ 81 virtual void RemoveMicrotasksCompletedCallback( 82 MicrotasksCompletedCallbackWithData callback, void* data = nullptr) = 0; 83 84 /** 85 * Runs microtasks if no microtask is running on this MicrotaskQueue instance. 86 */ 87 virtual void PerformCheckpoint(Isolate* isolate) = 0; 88 89 /** 90 * Returns true if a microtask is running on this MicrotaskQueue instance. 91 */ 92 virtual bool IsRunningMicrotasks() const = 0; 93 94 /** 95 * Returns the current depth of nested MicrotasksScope that has 96 * kRunMicrotasks. 97 */ 98 virtual int GetMicrotasksScopeDepth() const = 0; 99 100 MicrotaskQueue(const MicrotaskQueue&) = delete; 101 MicrotaskQueue& operator=(const MicrotaskQueue&) = delete; 102 103 private: 104 friend class internal::MicrotaskQueue; 105 MicrotaskQueue() = default; 106 }; 107 108 /** 109 * This scope is used to control microtasks when MicrotasksPolicy::kScoped 110 * is used on Isolate. In this mode every non-primitive call to V8 should be 111 * done inside some MicrotasksScope. 112 * Microtasks are executed when topmost MicrotasksScope marked as kRunMicrotasks 113 * exits. 114 * kDoNotRunMicrotasks should be used to annotate calls not intended to trigger 115 * microtasks. 116 */ 117 class V8_EXPORT V8_NODISCARD MicrotasksScope { 118 public: 119 enum Type { kRunMicrotasks, kDoNotRunMicrotasks }; 120 121 MicrotasksScope(Isolate* isolate, Type type); 122 MicrotasksScope(Isolate* isolate, MicrotaskQueue* microtask_queue, Type type); 123 ~MicrotasksScope(); 124 125 /** 126 * Runs microtasks if no kRunMicrotasks scope is currently active. 127 */ 128 static void PerformCheckpoint(Isolate* isolate); 129 130 /** 131 * Returns current depth of nested kRunMicrotasks scopes. 132 */ 133 static int GetCurrentDepth(Isolate* isolate); 134 135 /** 136 * Returns true while microtasks are being executed. 137 */ 138 static bool IsRunningMicrotasks(Isolate* isolate); 139 140 // Prevent copying. 141 MicrotasksScope(const MicrotasksScope&) = delete; 142 MicrotasksScope& operator=(const MicrotasksScope&) = delete; 143 144 private: 145 internal::Isolate* const isolate_; 146 internal::MicrotaskQueue* const microtask_queue_; 147 bool run_; 148 }; 149 150 } // namespace v8 151 152 #endif // INCLUDE_V8_MICROTASKS_QUEUE_H_ 153