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 |