1 /* 2 * Copyright (C) 2007-2009 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "ScheduledAction.h" 33 34 #include "Document.h" 35 #include "ScriptExecutionContext.h" 36 #include "ScriptSourceCode.h" 37 38 #include "V8Binding.h" 39 #include "V8Proxy.h" 40 #include "WorkerContext.h" 41 #include "WorkerContextExecutionProxy.h" 42 #include "WorkerThread.h" 43 44 namespace WebCore { 45 46 ScheduledAction::ScheduledAction(v8::Handle<v8::Context> context, v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value> argv[]) 47 : m_context(context) 48 , m_code(String(), KURL(), TextPosition1::belowRangePosition()) 49 { 50 m_function = v8::Persistent<v8::Function>::New(func); 51 52 #ifndef NDEBUG 53 V8GCController::registerGlobalHandle(SCHEDULED_ACTION, this, m_function); 54 #endif 55 56 m_argc = argc; 57 if (argc > 0) { 58 m_argv = new v8::Persistent<v8::Value>[argc]; 59 for (int i = 0; i < argc; i++) { 60 m_argv[i] = v8::Persistent<v8::Value>::New(argv[i]); 61 62 #ifndef NDEBUG 63 V8GCController::registerGlobalHandle(SCHEDULED_ACTION, this, m_argv[i]); 64 #endif 65 } 66 } else 67 m_argv = 0; 68 } 69 70 ScheduledAction::~ScheduledAction() 71 { 72 if (m_function.IsEmpty()) 73 return; 74 75 #ifndef NDEBUG 76 V8GCController::unregisterGlobalHandle(this, m_function); 77 #endif 78 m_function.Dispose(); 79 80 for (int i = 0; i < m_argc; i++) { 81 #ifndef NDEBUG 82 V8GCController::unregisterGlobalHandle(this, m_argv[i]); 83 #endif 84 m_argv[i].Dispose(); 85 } 86 87 if (m_argc > 0) 88 delete[] m_argv; 89 } 90 91 void ScheduledAction::execute(ScriptExecutionContext* context) 92 { 93 V8Proxy* proxy = V8Proxy::retrieve(context); 94 if (proxy) 95 execute(proxy); 96 #if ENABLE(WORKERS) 97 else if (context->isWorkerContext()) 98 execute(static_cast<WorkerContext*>(context)); 99 #endif 100 // It's possible that Javascript is disabled and that we have neither a V8Proxy 101 // nor a WorkerContext. Do nothing in that case. 102 } 103 104 void ScheduledAction::execute(V8Proxy* proxy) 105 { 106 ASSERT(proxy); 107 108 v8::HandleScope handleScope; 109 v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context.get()); 110 if (v8Context.IsEmpty()) 111 return; // JS may not be enabled. 112 113 v8::Context::Scope scope(v8Context); 114 115 proxy->setTimerCallback(true); 116 117 // FIXME: Need to implement timeouts for preempting a long-running script. 118 if (!m_function.IsEmpty() && m_function->IsFunction()) { 119 proxy->callFunction(v8::Persistent<v8::Function>::Cast(m_function), v8Context->Global(), m_argc, m_argv); 120 Document::updateStyleForAllDocuments(); 121 } else 122 proxy->evaluate(m_code, 0); 123 124 proxy->setTimerCallback(false); 125 } 126 127 #if ENABLE(WORKERS) 128 void ScheduledAction::execute(WorkerContext* workerContext) 129 { 130 // In a Worker, the execution should always happen on a worker thread. 131 ASSERT(workerContext->thread()->threadID() == currentThread()); 132 133 WorkerScriptController* scriptController = workerContext->script(); 134 135 if (!m_function.IsEmpty() && m_function->IsFunction()) { 136 v8::HandleScope handleScope; 137 v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context.get()); 138 ASSERT(!v8Context.IsEmpty()); 139 v8::Context::Scope scope(v8Context); 140 m_function->Call(v8Context->Global(), m_argc, m_argv); 141 } else 142 scriptController->evaluate(m_code); 143 } 144 #endif 145 146 } // namespace WebCore 147