v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singleShot)
{
    WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder());

    int argumentCount = args.Length();
    if (argumentCount < 1)
        return v8::Undefined();

    v8::Handle<v8::Value> function = args[0];
    int32_t timeout = argumentCount >= 2 ? args[1]->Int32Value() : 0;
    int timerId;

    WorkerContextExecutionProxy* proxy = workerContext->script()->proxy();
    if (!proxy)
        return v8::Undefined();

    v8::Handle<v8::Context> v8Context = proxy->context();
    if (function->IsString()) {
        WTF::String stringFunction = toWebCoreString(function);
        timerId = DOMTimer::install(workerContext, new ScheduledAction(v8Context, stringFunction, workerContext->url()), timeout, singleShot);
    } else if (function->IsFunction()) {
        size_t paramCount = argumentCount >= 2 ? argumentCount - 2 : 0;
        v8::Local<v8::Value>* params = 0;
        if (paramCount > 0) {
            params = new v8::Local<v8::Value>[paramCount];
            for (size_t i = 0; i < paramCount; ++i)
                params[i] = args[i+2];
        }
        // ScheduledAction takes ownership of actual params and releases them in its destructor.
        ScheduledAction* action = new ScheduledAction(v8Context, v8::Handle<v8::Function>::Cast(function), paramCount, params);
        delete [] params;
        timerId = DOMTimer::install(workerContext, action, timeout, singleShot);
    } else
        return v8::Undefined();

    return v8::Integer::New(timerId);
}
v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singleShot)
{
    WorkerContext* workerContext = V8WorkerContext::toNative(args.Holder());

    int argumentCount = args.Length();
    if (argumentCount < 1)
        return v8::Undefined();

    v8::Handle<v8::Value> function = args[0];
    int32_t timeout = argumentCount >= 2 ? args[1]->Int32Value() : 0;
    int timerId;

    WorkerContextExecutionProxy* proxy = workerContext->script()->proxy();
    if (!proxy)
        return v8::Undefined();

    v8::Handle<v8::Context> v8Context = proxy->context();
    if (function->IsString()) {
        if (ContentSecurityPolicy* policy = workerContext->contentSecurityPolicy()) {
            if (!policy->allowEval())
                return v8Integer(0, args.GetIsolate());
        }
        WTF::String stringFunction = toWebCoreString(function);
        timerId = DOMTimer::install(workerContext, adoptPtr(new ScheduledAction(v8Context, stringFunction, workerContext->url())), timeout, singleShot);
    } else if (function->IsFunction()) {
        size_t paramCount = argumentCount >= 2 ? argumentCount - 2 : 0;
        v8::Local<v8::Value>* params = 0;
        if (paramCount > 0) {
            params = new v8::Local<v8::Value>[paramCount];
            for (size_t i = 0; i < paramCount; ++i)
                params[i] = args[i+2];
        }
        // ScheduledAction takes ownership of actual params and releases them in its destructor.
        OwnPtr<ScheduledAction> action = adoptPtr(new ScheduledAction(v8Context, v8::Handle<v8::Function>::Cast(function), paramCount, params));
        // FIXME: We should use a OwnArrayPtr for params.
        delete [] params;
        timerId = DOMTimer::install(workerContext, action.release(), timeout, singleShot);
    } else
        return v8::Undefined();

    return v8Integer(timerId, args.GetIsolate());
}