CallDepthScope should track the current microtask scope

Tracking the context is not enough, as we might clear the context to
avoid repeatedly reentering the same context.

Also fix unittests that relied on the default microtask queue getting
automatically processed instead of the one of the current context.

Bug: chromium:728583
Change-Id: Ia9a51c513fc7363a518af86cc54c5bda26b5fbe8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2859850
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Jochen Eisinger <jochen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74303}
This commit is contained in:
Jochen Eisinger 2021-04-30 14:47:19 +02:00 committed by V8 LUCI CQ
parent d665f40fa2
commit a5c321024c
2 changed files with 16 additions and 9 deletions

View File

@ -139,6 +139,7 @@ class V8_NODISCARD CallDepthScope {
CallDepthScope(i::Isolate* isolate, Local<Context> context)
: isolate_(isolate),
context_(context),
did_enter_context_(false),
escaped_(false),
safe_for_termination_(isolate->next_v8_call_is_safe_for_termination()),
interrupts_scope_(isolate_, i::StackGuard::TERMINATE_EXECUTION,
@ -152,12 +153,11 @@ class V8_NODISCARD CallDepthScope {
if (!context.IsEmpty()) {
i::Handle<i::Context> env = Utils::OpenHandle(*context);
i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
if (!isolate->context().is_null() &&
isolate->context().native_context() == env->native_context()) {
context_ = Local<Context>();
} else {
if (isolate->context().is_null() ||
isolate->context().native_context() != env->native_context()) {
impl->SaveContext(isolate->context());
isolate->set_context(*env);
did_enter_context_ = true;
}
}
if (do_callback) isolate_->FireBeforeCallEnteredCallback();
@ -165,8 +165,10 @@ class V8_NODISCARD CallDepthScope {
~CallDepthScope() {
i::MicrotaskQueue* microtask_queue = isolate_->default_microtask_queue();
if (!context_.IsEmpty()) {
i::HandleScopeImplementer* impl = isolate_->handle_scope_implementer();
isolate_->set_context(impl->RestoreContext());
if (did_enter_context_) {
i::HandleScopeImplementer* impl = isolate_->handle_scope_implementer();
isolate_->set_context(impl->RestoreContext());
}
i::Handle<i::Context> env = Utils::OpenHandle(*context_);
microtask_queue = env->native_context().microtask_queue();
@ -213,9 +215,9 @@ class V8_NODISCARD CallDepthScope {
i::Isolate* const isolate_;
Local<Context> context_;
bool escaped_;
bool do_callback_;
bool safe_for_termination_;
bool did_enter_context_ : 1;
bool escaped_ : 1;
bool safe_for_termination_ : 1;
i::InterruptsScope interrupts_scope_;
i::Address previous_stack_height_;

View File

@ -248,6 +248,7 @@ TEST_P(MicrotaskQueueTest, VisitRoot) {
}
TEST_P(MicrotaskQueueTest, PromiseHandlerContext) {
microtask_queue()->set_microtasks_policy(MicrotasksPolicy::kExplicit);
Local<v8::Context> v8_context2 = v8::Context::New(v8_isolate());
Local<v8::Context> v8_context3 = v8::Context::New(v8_isolate());
Local<v8::Context> v8_context4 = v8::Context::New(v8_isolate());
@ -354,6 +355,7 @@ TEST_P(MicrotaskQueueTest, DetachGlobal_Enqueue) {
}
TEST_P(MicrotaskQueueTest, DetachGlobal_Run) {
microtask_queue()->set_microtasks_policy(MicrotasksPolicy::kExplicit);
EXPECT_EQ(0, microtask_queue()->size());
// Enqueue microtasks to the current context.
@ -392,6 +394,7 @@ TEST_P(MicrotaskQueueTest, DetachGlobal_Run) {
}
TEST_P(MicrotaskQueueTest, DetachGlobal_PromiseResolveThenableJobTask) {
microtask_queue()->set_microtasks_policy(MicrotasksPolicy::kExplicit);
RunJS(
"var resolve;"
"var promise = new Promise(r => { resolve = r; });"
@ -414,6 +417,7 @@ TEST_P(MicrotaskQueueTest, DetachGlobal_PromiseResolveThenableJobTask) {
}
TEST_P(MicrotaskQueueTest, DetachGlobal_ResolveThenableForeignThen) {
microtask_queue()->set_microtasks_policy(MicrotasksPolicy::kExplicit);
Handle<JSArray> result = RunJS<JSArray>(
"let result = [false];"
"result");
@ -425,6 +429,7 @@ TEST_P(MicrotaskQueueTest, DetachGlobal_ResolveThenableForeignThen) {
// Create a context with its own microtask queue.
std::unique_ptr<MicrotaskQueue> sub_microtask_queue =
MicrotaskQueue::New(isolate());
sub_microtask_queue->set_microtasks_policy(MicrotasksPolicy::kExplicit);
Local<v8::Context> sub_context = v8::Context::New(
v8_isolate(),
/* extensions= */ nullptr,