Commit 66b87c00 authored by dgozman's avatar dgozman Committed by Commit bot

Introduce MicrotasksCompletedCallback.

This calback is run after an attempt to run microtasks.

BUG=chromium:585949
LOG=Y

Review URL: https://codereview.chromium.org/1731773005

Cr-Commit-Position: refs/heads/master@{#34305}
parent b0a804da
......@@ -5055,7 +5055,8 @@ class PromiseRejectMessage {
typedef void (*PromiseRejectCallback)(PromiseRejectMessage message);
// --- Microtask Callback ---
// --- Microtasks Callbacks ---
typedef void (*MicrotasksCompletedCallback)(Isolate*);
typedef void (*MicrotaskCallback)(void* data);
// --- Failed Access Check Callback ---
......@@ -5895,6 +5896,25 @@ class V8_EXPORT Isolate {
*/
bool WillAutorunMicrotasks() const;
/**
* Experimental: adds a callback to notify the host application after
* microtasks were run. The callback is triggered by explicit RunMicrotasks
* call or automatic microtasks execution (see SetAutorunMicrotasks).
*
* Callback will trigger even if microtasks were attempted to run,
* but the microtasks queue was empty and no single microtask was actually
* executed.
*
* Executing scriptsinside the callback will not re-trigger microtasks and
* the callback.
*/
void AddMicrotasksCompletedCallback(MicrotasksCompletedCallback callback);
/**
* Removes callback that was installed by AddMicrotasksCompletedCallback.
*/
void RemoveMicrotasksCompletedCallback(MicrotasksCompletedCallback callback);
/**
* Sets a callback for counting the number of times a feature of V8 is used.
*/
......
......@@ -7460,6 +7460,21 @@ bool Isolate::WillAutorunMicrotasks() const {
}
void Isolate::AddMicrotasksCompletedCallback(
MicrotasksCompletedCallback callback) {
DCHECK(callback);
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->AddMicrotasksCompletedCallback(callback);
}
void Isolate::RemoveMicrotasksCompletedCallback(
MicrotasksCompletedCallback callback) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->RemoveMicrotasksCompletedCallback(callback);
}
void Isolate::SetUseCounterCallback(UseCounterCallback callback) {
reinterpret_cast<i::Isolate*>(this)->SetUseCounterCallback(callback);
}
......
......@@ -2766,7 +2766,12 @@ void Isolate::RunMicrotasks() {
// Increase call depth to prevent recursive callbacks.
v8::Isolate::SuppressMicrotaskExecutionScope suppress(
reinterpret_cast<v8::Isolate*>(this));
RunMicrotasksInternal();
FireMicrotasksCompletedCallback();
}
void Isolate::RunMicrotasksInternal() {
while (pending_microtask_count() > 0) {
HandleScope scope(this);
int num_tasks = pending_microtask_count();
......@@ -2808,6 +2813,32 @@ void Isolate::RunMicrotasks() {
}
void Isolate::AddMicrotasksCompletedCallback(
MicrotasksCompletedCallback callback) {
for (int i = 0; i < microtasks_completed_callbacks_.length(); i++) {
if (callback == microtasks_completed_callbacks_.at(i)) return;
}
microtasks_completed_callbacks_.Add(callback);
}
void Isolate::RemoveMicrotasksCompletedCallback(
MicrotasksCompletedCallback callback) {
for (int i = 0; i < microtasks_completed_callbacks_.length(); i++) {
if (callback == microtasks_completed_callbacks_.at(i)) {
microtasks_completed_callbacks_.Remove(i);
}
}
}
void Isolate::FireMicrotasksCompletedCallback() {
for (int i = 0; i < microtasks_completed_callbacks_.length(); i++) {
microtasks_completed_callbacks_.at(i)(reinterpret_cast<v8::Isolate*>(this));
}
}
void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) {
DCHECK(!use_counter_callback_);
use_counter_callback_ = callback;
......
......@@ -1061,6 +1061,10 @@ class Isolate {
void RemoveBeforeCallEnteredCallback(BeforeCallEnteredCallback callback);
void FireBeforeCallEnteredCallback();
void AddMicrotasksCompletedCallback(MicrotasksCompletedCallback callback);
void RemoveMicrotasksCompletedCallback(MicrotasksCompletedCallback callback);
void FireMicrotasksCompletedCallback();
void SetPromiseRejectCallback(PromiseRejectCallback callback);
void ReportPromiseReject(Handle<JSObject> promise, Handle<Object> value,
v8::PromiseRejectEvent event);
......@@ -1209,6 +1213,8 @@ class Isolate {
// the frame.
void RemoveMaterializedObjectsOnUnwind(StackFrame* frame);
void RunMicrotasksInternal();
base::Atomic32 id_;
EntryStackItem* entry_stack_;
int stack_trace_nesting_level_;
......@@ -1330,6 +1336,9 @@ class Isolate {
// List of callbacks when a Call completes.
List<CallCompletedCallback> call_completed_callbacks_;
// List of callbacks after microtasks were run.
List<MicrotasksCompletedCallback> microtasks_completed_callbacks_;
v8::Isolate::UseCounterCallback use_counter_callback_;
BasicBlockProfiler* basic_block_profiler_;
......
......@@ -21033,21 +21033,33 @@ TEST(RunMicrotasksIgnoresThrownExceptions) {
}
uint8_t microtasks_completed_callback_count = 0;
static void MicrotasksCompletedCallback(v8::Isolate* isolate) {
++microtasks_completed_callback_count;
}
TEST(SetAutorunMicrotasks) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
env->GetIsolate()->AddMicrotasksCompletedCallback(
&MicrotasksCompletedCallback);
CompileRun(
"var ext1Calls = 0;"
"var ext2Calls = 0;");
CompileRun("1+1;");
CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(0u, microtasks_completed_callback_count);
env->GetIsolate()->EnqueueMicrotask(
Function::New(env.local(), MicrotaskOne).ToLocalChecked());
CompileRun("1+1;");
CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(1u, microtasks_completed_callback_count);
env->GetIsolate()->SetAutorunMicrotasks(false);
env->GetIsolate()->EnqueueMicrotask(
......@@ -21057,20 +21069,24 @@ TEST(SetAutorunMicrotasks) {
CompileRun("1+1;");
CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(1u, microtasks_completed_callback_count);
env->GetIsolate()->RunMicrotasks();
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(2u, microtasks_completed_callback_count);
env->GetIsolate()->EnqueueMicrotask(
Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
CompileRun("1+1;");
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(2u, microtasks_completed_callback_count);
env->GetIsolate()->RunMicrotasks();
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(3u, microtasks_completed_callback_count);
env->GetIsolate()->SetAutorunMicrotasks(true);
env->GetIsolate()->EnqueueMicrotask(
......@@ -21078,6 +21094,7 @@ TEST(SetAutorunMicrotasks) {
CompileRun("1+1;");
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(4u, microtasks_completed_callback_count);
env->GetIsolate()->EnqueueMicrotask(
Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
......@@ -21086,11 +21103,22 @@ TEST(SetAutorunMicrotasks) {
CompileRun("1+1;");
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(4u, microtasks_completed_callback_count);
}
CompileRun("1+1;");
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(5u, microtasks_completed_callback_count);
env->GetIsolate()->RemoveMicrotasksCompletedCallback(
&MicrotasksCompletedCallback);
env->GetIsolate()->EnqueueMicrotask(
Function::New(env.local(), MicrotaskOne).ToLocalChecked());
CompileRun("1+1;");
CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
CHECK_EQ(5u, microtasks_completed_callback_count);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment