// --- Leave Script Callback ---
typedef void (*CallCompletedCallback)();
+// --- Microtask Callback ---
+typedef void (*MicrotaskCallback)(void* data);
+
// --- Failed Access Check Callback ---
typedef void (*FailedAccessCheckCallback)(Local<Object> target,
AccessType type,
*/
void EnqueueMicrotask(Handle<Function> microtask);
+ /**
+ * Experimental: Enqueues the callback to the Microtask Work Queue
+ */
+ void EnqueueMicrotask(MicrotaskCallback microtask, void* data = NULL);
+
/**
* Experimental: Controls whether the Microtask Work Queue is automatically
* run when the script call depth decrements to zero.
}
+void Isolate::EnqueueMicrotask(MicrotaskCallback microtask, void* data) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+ i::HandleScope scope(isolate);
+ i::Handle<i::CallHandlerInfo> callback_info =
+ i::Handle<i::CallHandlerInfo>::cast(
+ isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE));
+ SET_FIELD_WRAPPED(callback_info, set_callback, microtask);
+ SET_FIELD_WRAPPED(callback_info, set_data, data);
+ isolate->EnqueueMicrotask(callback_info);
+}
+
+
void Isolate::SetAutorunMicrotasks(bool autorun) {
reinterpret_cast<i::Isolate*>(this)->set_autorun_microtasks(autorun);
}
}
-void Isolate::EnqueueMicrotask(Handle<JSFunction> microtask) {
+void Isolate::EnqueueMicrotask(Handle<Object> microtask) {
+ ASSERT(microtask->IsJSFunction() || microtask->IsCallHandlerInfo());
Handle<FixedArray> queue(heap()->microtask_queue(), this);
int num_tasks = pending_microtask_count();
ASSERT(num_tasks <= queue->length());
for (int i = 0; i < num_tasks; i++) {
HandleScope scope(this);
- Handle<JSFunction> microtask(JSFunction::cast(queue->get(i)), this);
- Handle<Object> exception;
- MaybeHandle<Object> result = Execution::TryCall(
- microtask, factory()->undefined_value(), 0, NULL, &exception);
- // If execution is terminating, just bail out.
- if (result.is_null() &&
- !exception.is_null() &&
- *exception == heap()->termination_exception()) {
- // Clear out any remaining callbacks in the queue.
- heap()->set_microtask_queue(heap()->empty_fixed_array());
- set_pending_microtask_count(0);
- return;
+ Handle<Object> microtask(queue->get(i), this);
+ if (microtask->IsJSFunction()) {
+ Handle<JSFunction> microtask_function =
+ Handle<JSFunction>::cast(microtask);
+ Handle<Object> exception;
+ MaybeHandle<Object> result = Execution::TryCall(
+ microtask_function, factory()->undefined_value(),
+ 0, NULL, &exception);
+ // If execution is terminating, just bail out.
+ if (result.is_null() &&
+ !exception.is_null() &&
+ *exception == heap()->termination_exception()) {
+ // Clear out any remaining callbacks in the queue.
+ heap()->set_microtask_queue(heap()->empty_fixed_array());
+ set_pending_microtask_count(0);
+ return;
+ }
+ } else {
+ Handle<CallHandlerInfo> callback_info =
+ Handle<CallHandlerInfo>::cast(microtask);
+ v8::MicrotaskCallback callback =
+ v8::ToCData<v8::MicrotaskCallback>(callback_info->callback());
+ void* data = v8::ToCData<void*>(callback_info->data());
+ callback(data);
}
}
}
void RemoveCallCompletedCallback(CallCompletedCallback callback);
void FireCallCompletedCallback();
- void EnqueueMicrotask(Handle<JSFunction> microtask);
+ void EnqueueMicrotask(Handle<Object> microtask);
void RunMicrotasks();
private:
}
+void* g_passed_to_three = NULL;
+
+
+static void MicrotaskThree(void* data) {
+ g_passed_to_three = data;
+}
+
+
TEST(EnqueueMicrotask) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
CompileRun("1+1;");
CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
+
+ g_passed_to_three = NULL;
+ env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
+ CompileRun("1+1;");
+ CHECK_EQ(NULL, g_passed_to_three);
+ CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
+ CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
+
+ int dummy;
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskOne));
+ env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
+ env->GetIsolate()->EnqueueMicrotask(
+ Function::New(env->GetIsolate(), MicrotaskTwo));
+ CompileRun("1+1;");
+ CHECK_EQ(&dummy, g_passed_to_three);
+ CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value());
+ CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
+ g_passed_to_three = NULL;
}