| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2009, 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 | 32 |
| 33 #include "bindings/v8/WorkerScriptController.h" | 33 #include "bindings/v8/WorkerScriptController.h" |
| 34 | 34 |
| 35 #include "V8DedicatedWorkerContext.h" | 35 #include "V8DedicatedWorkerGlobalScope.h" |
| 36 #include "V8SharedWorkerContext.h" | 36 #include "V8SharedWorkerGlobalScope.h" |
| 37 #include "V8WorkerContext.h" | 37 #include "V8WorkerGlobalScope.h" |
| 38 #include "bindings/v8/ScriptSourceCode.h" | 38 #include "bindings/v8/ScriptSourceCode.h" |
| 39 #include "bindings/v8/ScriptValue.h" | 39 #include "bindings/v8/ScriptValue.h" |
| 40 #include "bindings/v8/V8GCController.h" | 40 #include "bindings/v8/V8GCController.h" |
| 41 #include "bindings/v8/V8Initializer.h" | 41 #include "bindings/v8/V8Initializer.h" |
| 42 #include "bindings/v8/V8ObjectConstructor.h" | 42 #include "bindings/v8/V8ObjectConstructor.h" |
| 43 #include "bindings/v8/V8ScriptRunner.h" | 43 #include "bindings/v8/V8ScriptRunner.h" |
| 44 #include "bindings/v8/WrapperTypeInfo.h" | 44 #include "bindings/v8/WrapperTypeInfo.h" |
| 45 #include "core/inspector/ScriptCallStack.h" | 45 #include "core/inspector/ScriptCallStack.h" |
| 46 #include "core/page/DOMTimer.h" | 46 #include "core/page/DOMTimer.h" |
| 47 #include "core/workers/WorkerContext.h" | 47 #include "core/workers/WorkerGlobalScope.h" |
| 48 #include "core/workers/WorkerObjectProxy.h" | 48 #include "core/workers/WorkerObjectProxy.h" |
| 49 #include "core/workers/WorkerThread.h" | 49 #include "core/workers/WorkerThread.h" |
| 50 #include <v8.h> | 50 #include <v8.h> |
| 51 | 51 |
| 52 #include "public/platform/Platform.h" | 52 #include "public/platform/Platform.h" |
| 53 #include "public/platform/WebWorkerRunLoop.h" | 53 #include "public/platform/WebWorkerRunLoop.h" |
| 54 | 54 |
| 55 namespace WebCore { | 55 namespace WebCore { |
| 56 | 56 |
| 57 WorkerScriptController::WorkerScriptController(WorkerContext* workerContext) | 57 WorkerScriptController::WorkerScriptController(WorkerGlobalScope* workerGlobalSc
ope) |
| 58 : m_workerContext(workerContext) | 58 : m_workerGlobalScope(workerGlobalScope) |
| 59 , m_isolate(v8::Isolate::New()) | 59 , m_isolate(v8::Isolate::New()) |
| 60 , m_executionForbidden(false) | 60 , m_executionForbidden(false) |
| 61 , m_executionScheduledToTerminate(false) | 61 , m_executionScheduledToTerminate(false) |
| 62 { | 62 { |
| 63 m_isolate->Enter(); | 63 m_isolate->Enter(); |
| 64 v8::V8::Initialize(); | 64 v8::V8::Initialize(); |
| 65 V8PerIsolateData* data = V8PerIsolateData::create(m_isolate); | 65 V8PerIsolateData* data = V8PerIsolateData::create(m_isolate); |
| 66 m_domDataStore = adoptPtr(new DOMDataStore(WorkerWorld)); | 66 m_domDataStore = adoptPtr(new DOMDataStore(WorkerWorld)); |
| 67 data->setWorkerDOMDataStore(m_domDataStore.get()); | 67 data->setWorkerDOMDataStore(m_domDataStore.get()); |
| 68 | 68 |
| 69 V8Initializer::initializeWorker(m_isolate); | 69 V8Initializer::initializeWorker(m_isolate); |
| 70 } | 70 } |
| 71 | 71 |
| 72 WorkerScriptController::~WorkerScriptController() | 72 WorkerScriptController::~WorkerScriptController() |
| 73 { | 73 { |
| 74 m_domDataStore.clear(); | 74 m_domDataStore.clear(); |
| 75 | 75 |
| 76 // The corresponding call to didStartWorkerRunLoop is in | 76 // The corresponding call to didStartWorkerRunLoop is in |
| 77 // WorkerThread::workerThread(). | 77 // WorkerThread::workerThread(). |
| 78 // See http://webkit.org/b/83104#c14 for why this is here. | 78 // See http://webkit.org/b/83104#c14 for why this is here. |
| 79 WebKit::Platform::current()->didStopWorkerRunLoop(WebKit::WebWorkerRunLoop(&
m_workerContext->thread()->runLoop())); | 79 WebKit::Platform::current()->didStopWorkerRunLoop(WebKit::WebWorkerRunLoop(&
m_workerGlobalScope->thread()->runLoop())); |
| 80 | 80 |
| 81 disposeContext(); | 81 disposeContext(); |
| 82 V8PerIsolateData::dispose(m_isolate); | 82 V8PerIsolateData::dispose(m_isolate); |
| 83 m_isolate->Exit(); | 83 m_isolate->Exit(); |
| 84 m_isolate->Dispose(); | 84 m_isolate->Dispose(); |
| 85 } | 85 } |
| 86 | 86 |
| 87 void WorkerScriptController::disposeContext() | 87 void WorkerScriptController::disposeContext() |
| 88 { | 88 { |
| 89 m_perContextData.clear(); | 89 m_perContextData.clear(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 107 m_perContextData = V8PerContextData::create(m_context.get()); | 107 m_perContextData = V8PerContextData::create(m_context.get()); |
| 108 if (!m_perContextData->init()) { | 108 if (!m_perContextData->init()) { |
| 109 disposeContext(); | 109 disposeContext(); |
| 110 return false; | 110 return false; |
| 111 } | 111 } |
| 112 | 112 |
| 113 // Set DebugId for the new context. | 113 // Set DebugId for the new context. |
| 114 context->SetEmbedderData(0, v8::String::NewSymbol("worker")); | 114 context->SetEmbedderData(0, v8::String::NewSymbol("worker")); |
| 115 | 115 |
| 116 // Create a new JS object and use it as the prototype for the shadow global
object. | 116 // Create a new JS object and use it as the prototype for the shadow global
object. |
| 117 WrapperTypeInfo* contextType = &V8DedicatedWorkerContext::info; | 117 WrapperTypeInfo* contextType = &V8DedicatedWorkerGlobalScope::info; |
| 118 if (!m_workerContext->isDedicatedWorkerContext()) | 118 if (!m_workerGlobalScope->isDedicatedWorkerGlobalScope()) |
| 119 contextType = &V8SharedWorkerContext::info; | 119 contextType = &V8SharedWorkerGlobalScope::info; |
| 120 v8::Handle<v8::Function> workerContextConstructor = m_perContextData->constr
uctorForType(contextType); | 120 v8::Handle<v8::Function> workerGlobalScopeConstructor = m_perContextData->co
nstructorForType(contextType); |
| 121 v8::Local<v8::Object> jsWorkerContext = V8ObjectConstructor::newInstance(wor
kerContextConstructor); | 121 v8::Local<v8::Object> jsWorkerGlobalScope = V8ObjectConstructor::newInstance
(workerGlobalScopeConstructor); |
| 122 if (jsWorkerContext.IsEmpty()) { | 122 if (jsWorkerGlobalScope.IsEmpty()) { |
| 123 disposeContext(); | 123 disposeContext(); |
| 124 return false; | 124 return false; |
| 125 } | 125 } |
| 126 | 126 |
| 127 V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<WorkerContext>(m_workerC
ontext), contextType, jsWorkerContext, m_isolate, WrapperConfiguration::Dependen
t); | 127 V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<WorkerGlobalScope>(m_wor
kerGlobalScope), contextType, jsWorkerGlobalScope, m_isolate, WrapperConfigurati
on::Dependent); |
| 128 | 128 |
| 129 // Insert the object instance as the prototype of the shadow object. | 129 // Insert the object instance as the prototype of the shadow object. |
| 130 v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_context
.newLocal(m_isolate)->Global()->GetPrototype()); | 130 v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_context
.newLocal(m_isolate)->Global()->GetPrototype()); |
| 131 globalObject->SetPrototype(jsWorkerContext); | 131 globalObject->SetPrototype(jsWorkerGlobalScope); |
| 132 | 132 |
| 133 return true; | 133 return true; |
| 134 } | 134 } |
| 135 | 135 |
| 136 ScriptValue WorkerScriptController::evaluate(const String& script, const String&
fileName, const TextPosition& scriptStartPosition, WorkerContextExecutionState*
state) | 136 ScriptValue WorkerScriptController::evaluate(const String& script, const String&
fileName, const TextPosition& scriptStartPosition, WorkerGlobalScopeExecutionSt
ate* state) |
| 137 { | 137 { |
| 138 V8GCController::checkMemoryUsage(); | 138 V8GCController::checkMemoryUsage(); |
| 139 | 139 |
| 140 v8::HandleScope handleScope(m_isolate); | 140 v8::HandleScope handleScope(m_isolate); |
| 141 | 141 |
| 142 if (!initializeContextIfNeeded()) | 142 if (!initializeContextIfNeeded()) |
| 143 return ScriptValue(); | 143 return ScriptValue(); |
| 144 | 144 |
| 145 v8::Handle<v8::Context> context = m_context.newLocal(m_isolate); | 145 v8::Handle<v8::Context> context = m_context.newLocal(m_isolate); |
| 146 if (!m_disableEvalPending.isEmpty()) { | 146 if (!m_disableEvalPending.isEmpty()) { |
| 147 context->AllowCodeGenerationFromStrings(false); | 147 context->AllowCodeGenerationFromStrings(false); |
| 148 context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_disableE
valPending, m_isolate)); | 148 context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_disableE
valPending, m_isolate)); |
| 149 m_disableEvalPending = String(); | 149 m_disableEvalPending = String(); |
| 150 } | 150 } |
| 151 | 151 |
| 152 v8::Context::Scope scope(context); | 152 v8::Context::Scope scope(context); |
| 153 | 153 |
| 154 v8::TryCatch block; | 154 v8::TryCatch block; |
| 155 | 155 |
| 156 v8::Handle<v8::String> scriptString = v8String(script, m_isolate); | 156 v8::Handle<v8::String> scriptString = v8String(script, m_isolate); |
| 157 v8::Handle<v8::Script> compiledScript = V8ScriptRunner::compileScript(script
String, fileName, scriptStartPosition, 0, m_isolate); | 157 v8::Handle<v8::Script> compiledScript = V8ScriptRunner::compileScript(script
String, fileName, scriptStartPosition, 0, m_isolate); |
| 158 v8::Local<v8::Value> result = V8ScriptRunner::runCompiledScript(compiledScri
pt, m_workerContext); | 158 v8::Local<v8::Value> result = V8ScriptRunner::runCompiledScript(compiledScri
pt, m_workerGlobalScope); |
| 159 | 159 |
| 160 if (!block.CanContinue()) { | 160 if (!block.CanContinue()) { |
| 161 m_workerContext->script()->forbidExecution(); | 161 m_workerGlobalScope->script()->forbidExecution(); |
| 162 return ScriptValue(); | 162 return ScriptValue(); |
| 163 } | 163 } |
| 164 | 164 |
| 165 if (block.HasCaught()) { | 165 if (block.HasCaught()) { |
| 166 v8::Local<v8::Message> message = block.Message(); | 166 v8::Local<v8::Message> message = block.Message(); |
| 167 state->hadException = true; | 167 state->hadException = true; |
| 168 state->errorMessage = toWebCoreString(message->Get()); | 168 state->errorMessage = toWebCoreString(message->Get()); |
| 169 state->lineNumber = message->GetLineNumber(); | 169 state->lineNumber = message->GetLineNumber(); |
| 170 state->sourceURL = toWebCoreString(message->GetScriptResourceName()); | 170 state->sourceURL = toWebCoreString(message->GetScriptResourceName()); |
| 171 if (m_workerContext->sanitizeScriptError(state->errorMessage, state->lin
eNumber, state->sourceURL)) | 171 if (m_workerGlobalScope->sanitizeScriptError(state->errorMessage, state-
>lineNumber, state->sourceURL)) |
| 172 state->exception = throwError(v8GeneralError, state->errorMessage.ut
f8().data(), m_isolate); | 172 state->exception = throwError(v8GeneralError, state->errorMessage.ut
f8().data(), m_isolate); |
| 173 else | 173 else |
| 174 state->exception = ScriptValue(block.Exception()); | 174 state->exception = ScriptValue(block.Exception()); |
| 175 | 175 |
| 176 block.Reset(); | 176 block.Reset(); |
| 177 } else | 177 } else |
| 178 state->hadException = false; | 178 state->hadException = false; |
| 179 | 179 |
| 180 if (result.IsEmpty() || result->IsUndefined()) | 180 if (result.IsEmpty() || result->IsUndefined()) |
| 181 return ScriptValue(); | 181 return ScriptValue(); |
| 182 | 182 |
| 183 return ScriptValue(result); | 183 return ScriptValue(result); |
| 184 } | 184 } |
| 185 | 185 |
| 186 void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, Script
Value* exception) | 186 void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, Script
Value* exception) |
| 187 { | 187 { |
| 188 if (isExecutionForbidden()) | 188 if (isExecutionForbidden()) |
| 189 return; | 189 return; |
| 190 | 190 |
| 191 WorkerContextExecutionState state; | 191 WorkerGlobalScopeExecutionState state; |
| 192 evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startPos
ition(), &state); | 192 evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startPos
ition(), &state); |
| 193 if (state.hadException) { | 193 if (state.hadException) { |
| 194 if (exception) | 194 if (exception) |
| 195 *exception = state.exception; | 195 *exception = state.exception; |
| 196 else | 196 else |
| 197 m_workerContext->reportException(state.errorMessage, state.lineNumbe
r, state.sourceURL, 0); | 197 m_workerGlobalScope->reportException(state.errorMessage, state.lineN
umber, state.sourceURL, 0); |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 | 200 |
| 201 void WorkerScriptController::scheduleExecutionTermination() | 201 void WorkerScriptController::scheduleExecutionTermination() |
| 202 { | 202 { |
| 203 // The mutex provides a memory barrier to ensure that once | 203 // The mutex provides a memory barrier to ensure that once |
| 204 // termination is scheduled, isExecutionTerminating will | 204 // termination is scheduled, isExecutionTerminating will |
| 205 // accurately reflect that state when called from another thread. | 205 // accurately reflect that state when called from another thread. |
| 206 { | 206 { |
| 207 MutexLocker locker(m_scheduledTerminationMutex); | 207 MutexLocker locker(m_scheduledTerminationMutex); |
| 208 m_executionScheduledToTerminate = true; | 208 m_executionScheduledToTerminate = true; |
| 209 } | 209 } |
| 210 v8::V8::TerminateExecution(m_isolate); | 210 v8::V8::TerminateExecution(m_isolate); |
| 211 } | 211 } |
| 212 | 212 |
| 213 bool WorkerScriptController::isExecutionTerminating() const | 213 bool WorkerScriptController::isExecutionTerminating() const |
| 214 { | 214 { |
| 215 // See comments in scheduleExecutionTermination regarding mutex usage. | 215 // See comments in scheduleExecutionTermination regarding mutex usage. |
| 216 MutexLocker locker(m_scheduledTerminationMutex); | 216 MutexLocker locker(m_scheduledTerminationMutex); |
| 217 return m_executionScheduledToTerminate; | 217 return m_executionScheduledToTerminate; |
| 218 } | 218 } |
| 219 | 219 |
| 220 void WorkerScriptController::forbidExecution() | 220 void WorkerScriptController::forbidExecution() |
| 221 { | 221 { |
| 222 ASSERT(m_workerContext->isContextThread()); | 222 ASSERT(m_workerGlobalScope->isContextThread()); |
| 223 m_executionForbidden = true; | 223 m_executionForbidden = true; |
| 224 } | 224 } |
| 225 | 225 |
| 226 bool WorkerScriptController::isExecutionForbidden() const | 226 bool WorkerScriptController::isExecutionForbidden() const |
| 227 { | 227 { |
| 228 ASSERT(m_workerContext->isContextThread()); | 228 ASSERT(m_workerGlobalScope->isContextThread()); |
| 229 return m_executionForbidden; | 229 return m_executionForbidden; |
| 230 } | 230 } |
| 231 | 231 |
| 232 void WorkerScriptController::disableEval(const String& errorMessage) | 232 void WorkerScriptController::disableEval(const String& errorMessage) |
| 233 { | 233 { |
| 234 m_disableEvalPending = errorMessage; | 234 m_disableEvalPending = errorMessage; |
| 235 } | 235 } |
| 236 | 236 |
| 237 void WorkerScriptController::setException(const ScriptValue& exception) | 237 void WorkerScriptController::setException(const ScriptValue& exception) |
| 238 { | 238 { |
| 239 throwError(exception.v8Value(), m_isolate); | 239 throwError(exception.v8Value(), m_isolate); |
| 240 } | 240 } |
| 241 | 241 |
| 242 WorkerScriptController* WorkerScriptController::controllerForContext() | 242 WorkerScriptController* WorkerScriptController::controllerForContext() |
| 243 { | 243 { |
| 244 // Happens on frame destruction, check otherwise GetCurrent() will crash. | 244 // Happens on frame destruction, check otherwise GetCurrent() will crash. |
| 245 if (!v8::Context::InContext()) | 245 if (!v8::Context::InContext()) |
| 246 return 0; | 246 return 0; |
| 247 v8::Handle<v8::Context> context = v8::Context::GetCurrent(); | 247 v8::Handle<v8::Context> context = v8::Context::GetCurrent(); |
| 248 v8::Handle<v8::Object> global = context->Global(); | 248 v8::Handle<v8::Object> global = context->Global(); |
| 249 global = global->FindInstanceInPrototypeChain(V8WorkerContext::GetTemplate(c
ontext->GetIsolate(), WorkerWorld)); | 249 global = global->FindInstanceInPrototypeChain(V8WorkerGlobalScope::GetTempla
te(context->GetIsolate(), WorkerWorld)); |
| 250 // Return 0 if the current executing context is not the worker context. | 250 // Return 0 if the current executing context is not the worker context. |
| 251 if (global.IsEmpty()) | 251 if (global.IsEmpty()) |
| 252 return 0; | 252 return 0; |
| 253 WorkerContext* workerContext = V8WorkerContext::toNative(global); | 253 WorkerGlobalScope* workerGlobalScope = V8WorkerGlobalScope::toNative(global)
; |
| 254 return workerContext->script(); | 254 return workerGlobalScope->script(); |
| 255 } | 255 } |
| 256 | 256 |
| 257 } // namespace WebCore | 257 } // namespace WebCore |
| OLD | NEW |