RunMicrotasks() executes pending tasks and swaps the old array with a new array. However, the new array contains the reference to the current context as its creation context. This prevents the context from gc-ed until RunMicrotasks() is executed in the different context.
BUG=crbug.com/367016
LOG=y
R=rafaelw@chromium.org, rossberg@chromium.org
Review URL: https://codereview.chromium.org/
250883002
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21111
ce2b1a6d-e550-0410-aec6-
3dcde31c8c00
void Genesis::InstallExperimentalNativeFunctions() {
INSTALL_NATIVE(JSFunction, "RunMicrotasks", run_microtasks);
- INSTALL_NATIVE(JSFunction, "EnqueueExternalMicrotask",
- enqueue_external_microtask);
+ INSTALL_NATIVE(JSFunction, "EnqueueMicrotask", enqueue_microtask);
if (FLAG_harmony_promises) {
INSTALL_NATIVE(JSFunction, "IsPromise", is_promise);
V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
error_message_for_code_gen_from_strings) \
V(RUN_MICROTASKS_INDEX, JSFunction, run_microtasks) \
- V(ENQUEUE_EXTERNAL_MICROTASK_INDEX, JSFunction, enqueue_external_microtask) \
+ V(ENQUEUE_MICROTASK_INDEX, JSFunction, enqueue_microtask) \
V(IS_PROMISE_INDEX, JSFunction, is_promise) \
V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \
V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \
ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX,
RUN_MICROTASKS_INDEX,
- ENQUEUE_EXTERNAL_MICROTASK_INDEX,
+ ENQUEUE_MICROTASK_INDEX,
IS_PROMISE_INDEX,
PROMISE_CREATE_INDEX,
PROMISE_RESOLVE_INDEX,
Handle<Object> args[] = { microtask };
Execution::Call(
isolate,
- isolate->enqueue_external_microtask(),
+ isolate->enqueue_microtask(),
isolate->factory()->undefined_value(),
1,
args).Check();
var callbackInfo = CallbackInfoNormalize(callback);
if (IS_NULL(GetPendingObservers())) {
SetPendingObservers(nullProtoObject())
- GetMicrotaskQueue().push(ObserveMicrotaskRunner);
- %SetMicrotaskPending(true);
+ EnqueueMicrotask(ObserveMicrotaskRunner);
}
GetPendingObservers()[callbackInfo.priority] = callback;
callbackInfo.push(changeRecord);
}
function PromiseEnqueue(value, tasks) {
- GetMicrotaskQueue().push(function() {
+ EnqueueMicrotask(function() {
for (var i = 0; i < tasks.length; i += 2) {
PromiseHandle(value, tasks[i], tasks[i + 1])
}
});
-
- %SetMicrotaskPending(true);
}
function PromiseHandle(value, handler, deferred) {
// Eventually, we should move to a real event queue that allows to maintain
// relative ordering of different kinds of tasks.
-function GetMicrotaskQueue() {
- var microtaskState = %GetMicrotaskState();
- if (IS_UNDEFINED(microtaskState.queue)) {
- microtaskState.queue = new InternalArray;
- }
- return microtaskState.queue;
-}
-
function RunMicrotasks() {
while (%SetMicrotaskPending(false)) {
var microtaskState = %GetMicrotaskState();
return;
var microtasks = microtaskState.queue;
- microtaskState.queue = new InternalArray;
+ microtaskState.queue = null;
for (var i = 0; i < microtasks.length; i++) {
microtasks[i]();
}
}
-function EnqueueExternalMicrotask(fn) {
- GetMicrotaskQueue().push(fn);
+function EnqueueMicrotask(fn) {
+ var microtaskState = %GetMicrotaskState();
+ if (IS_UNDEFINED(microtaskState.queue) || IS_NULL(microtaskState.queue)) {
+ microtaskState.queue = new InternalArray;
+ }
+ microtaskState.queue.push(fn);
%SetMicrotaskPending(true);
}