Revision: 21658
Author: [email protected]
Date: Tue Jun 3 20:12:19 2014 UTC
Log: Add API support for passing a C++ function as a microtask callback
This allows embedders to enqueue microtasks without having any v8::Context
handy, as happens in Blink in some cases (such as DOM mutations due to
editing
triggering MutationObservers).
LOG=Y
[email protected]
Review URL: https://codereview.chromium.org/306053003
http://code.google.com/p/v8/source/detail?r=21658
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/test/cctest/test-api.cc
=======================================
--- /branches/bleeding_edge/include/v8.h Tue Jun 3 14:38:35 2014 UTC
+++ /branches/bleeding_edge/include/v8.h Tue Jun 3 20:12:19 2014 UTC
@@ -3966,6 +3966,9 @@
// --- 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,
@@ -4385,6 +4388,11 @@
*/
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.
=======================================
--- /branches/bleeding_edge/src/api.cc Tue Jun 3 14:38:35 2014 UTC
+++ /branches/bleeding_edge/src/api.cc Tue Jun 3 20:12:19 2014 UTC
@@ -6677,6 +6677,18 @@
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->EnqueueMicrotask(Utils::OpenHandle(*microtask));
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/isolate.cc Tue Jun 3 14:39:55 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc Tue Jun 3 20:12:19 2014 UTC
@@ -2262,7 +2262,8 @@
}
-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());
@@ -2301,18 +2302,30 @@
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);
}
}
}
=======================================
--- /branches/bleeding_edge/src/isolate.h Tue Jun 3 08:12:43 2014 UTC
+++ /branches/bleeding_edge/src/isolate.h Tue Jun 3 20:12:19 2014 UTC
@@ -1077,7 +1077,7 @@
void RemoveCallCompletedCallback(CallCompletedCallback callback);
void FireCallCompletedCallback();
- void EnqueueMicrotask(Handle<JSFunction> microtask);
+ void EnqueueMicrotask(Handle<Object> microtask);
void RunMicrotasks();
private:
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Tue Jun 3 15:45:38
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-api.cc Tue Jun 3 20:12:19
2014 UTC
@@ -20687,6 +20687,14 @@
v8::HandleScope scope(info.GetIsolate());
CompileRun("ext2Calls++;");
}
+
+
+void* g_passed_to_three = NULL;
+
+
+static void MicrotaskThree(void* data) {
+ g_passed_to_three = data;
+}
TEST(EnqueueMicrotask) {
@@ -20722,6 +20730,25 @@
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;
}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.