Index: src/api.cc |
diff --git a/src/api.cc b/src/api.cc |
index bf57a3aa14376ab17e6c42a8004561e72a2f80e6..0158d3ab56dc4706a9e6618a4b3a6af3f53d9acb 100644 |
--- a/src/api.cc |
+++ b/src/api.cc |
@@ -157,6 +157,18 @@ class InternalEscapableScope : public v8::EscapableHandleScope { |
}; |
+#ifdef V8_ENABLE_CHECKS |
+void CheckMicrotasksScopesConsistency(i::Isolate* isolate) { |
+ auto handle_scope_implementer = isolate->handle_scope_implementer(); |
+ if (handle_scope_implementer->microtasks_policy() == |
+ v8::MicrotasksPolicy::kScoped) { |
+ DCHECK(handle_scope_implementer->GetMicrotasksScopeDepth() || |
+ !handle_scope_implementer->DebugMicrotasksScopeDepthIsZero()); |
+ } |
+} |
+#endif |
+ |
+ |
class CallDepthScope { |
public: |
explicit CallDepthScope(i::Isolate* isolate, Local<Context> context, |
@@ -176,6 +188,9 @@ class CallDepthScope { |
if (!context_.IsEmpty()) context_->Exit(); |
if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth(); |
if (do_callback_) isolate_->FireCallCompletedCallback(); |
+#ifdef V8_ENABLE_CHECKS |
+ if (do_callback_) CheckMicrotasksScopesConsistency(isolate_); |
+#endif |
} |
void Escape() { |
@@ -7298,10 +7313,12 @@ Isolate::SuppressMicrotaskExecutionScope::SuppressMicrotaskExecutionScope( |
Isolate* isolate) |
: isolate_(reinterpret_cast<i::Isolate*>(isolate)) { |
isolate_->handle_scope_implementer()->IncrementCallDepth(); |
+ isolate_->handle_scope_implementer()->IncrementMicrotasksSuppressions(); |
} |
Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() { |
+ isolate_->handle_scope_implementer()->DecrementMicrotasksSuppressions(); |
isolate_->handle_scope_implementer()->DecrementCallDepth(); |
} |
@@ -7443,6 +7460,7 @@ void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) { |
void Isolate::RunMicrotasks() { |
+ DCHECK(MicrotasksPolicy::kScoped != GetMicrotasksPolicy()); |
reinterpret_cast<i::Isolate*>(this)->RunMicrotasks(); |
} |
@@ -7466,12 +7484,26 @@ void Isolate::EnqueueMicrotask(MicrotaskCallback microtask, void* data) { |
void Isolate::SetAutorunMicrotasks(bool autorun) { |
- reinterpret_cast<i::Isolate*>(this)->set_autorun_microtasks(autorun); |
+ SetMicrotasksPolicy( |
+ autorun ? MicrotasksPolicy::kAuto : MicrotasksPolicy::kExplicit); |
} |
bool Isolate::WillAutorunMicrotasks() const { |
- return reinterpret_cast<const i::Isolate*>(this)->autorun_microtasks(); |
+ return GetMicrotasksPolicy() == MicrotasksPolicy::kAuto; |
+} |
+ |
+ |
+void Isolate::SetMicrotasksPolicy(MicrotasksPolicy policy) { |
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); |
+ isolate->handle_scope_implementer()->set_microtasks_policy(policy); |
+} |
+ |
+ |
+MicrotasksPolicy Isolate::GetMicrotasksPolicy() const { |
+ i::Isolate* isolate = |
+ reinterpret_cast<i::Isolate*>(const_cast<Isolate*>(this)); |
+ return isolate->handle_scope_implementer()->microtasks_policy(); |
} |
@@ -7710,6 +7742,49 @@ void Isolate::VisitWeakHandles(PersistentHandleVisitor* visitor) { |
} |
+MicrotasksScope::MicrotasksScope(Isolate* isolate, MicrotasksScope::Type type) |
+ : isolate_(reinterpret_cast<i::Isolate*>(isolate)), |
+ run_(type == MicrotasksScope::kRunMicrotasks) { |
+ auto handle_scope_implementer = isolate_->handle_scope_implementer(); |
+ if (run_) handle_scope_implementer->IncrementMicrotasksScopeDepth(); |
+#ifdef V8_ENABLE_CHECKS |
+ if (!run_) handle_scope_implementer->IncrementDebugMicrotasksScopeDepth(); |
+#endif |
+} |
+ |
+ |
+MicrotasksScope::~MicrotasksScope() { |
+ auto handle_scope_implementer = isolate_->handle_scope_implementer(); |
+ if (run_) { |
+ handle_scope_implementer->DecrementMicrotasksScopeDepth(); |
+ if (MicrotasksPolicy::kScoped == |
+ handle_scope_implementer->microtasks_policy()) { |
+ PerformCheckpoint(reinterpret_cast<Isolate*>(isolate_)); |
+ } |
+ } |
+#ifdef V8_ENABLE_CHECKS |
+ if (!run_) handle_scope_implementer->DecrementDebugMicrotasksScopeDepth(); |
+#endif |
+} |
+ |
+ |
+void MicrotasksScope::PerformCheckpoint(Isolate* v8Isolate) { |
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8Isolate); |
+ if (IsExecutionTerminatingCheck(isolate)) return; |
+ auto handle_scope_implementer = isolate->handle_scope_implementer(); |
+ if (!handle_scope_implementer->GetMicrotasksScopeDepth() && |
+ !handle_scope_implementer->HasMicrotasksSuppressions()) { |
+ isolate->RunMicrotasks(); |
+ } |
+} |
+ |
+ |
+int MicrotasksScope::GetCurrentDepth(Isolate* v8Isolate) { |
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8Isolate); |
+ return isolate->handle_scope_implementer()->GetMicrotasksScopeDepth(); |
+} |
+ |
+ |
String::Utf8Value::Utf8Value(v8::Local<v8::Value> obj) |
: str_(NULL), length_(0) { |
if (obj.IsEmpty()) return; |