Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: Source/bindings/core/v8/WorkerScriptController.cpp

Issue 404513002: Propagate nested importScripts() error events outwards. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Use STACK_ALLOCATED() Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 #include "core/workers/WorkerGlobalScope.h" 51 #include "core/workers/WorkerGlobalScope.h"
52 #include "core/workers/WorkerObjectProxy.h" 52 #include "core/workers/WorkerObjectProxy.h"
53 #include "core/workers/WorkerThread.h" 53 #include "core/workers/WorkerThread.h"
54 #include "platform/heap/ThreadState.h" 54 #include "platform/heap/ThreadState.h"
55 #include "public/platform/Platform.h" 55 #include "public/platform/Platform.h"
56 #include "public/platform/WebWorkerRunLoop.h" 56 #include "public/platform/WebWorkerRunLoop.h"
57 #include <v8.h> 57 #include <v8.h>
58 58
59 namespace WebCore { 59 namespace WebCore {
60 60
61 class WorkerScriptController::WorkerGlobalScopeExecutionState FINAL {
62 STACK_ALLOCATED();
63 public:
64 explicit WorkerGlobalScopeExecutionState(WorkerScriptController* controller)
65 : hadException(false)
66 , lineNumber(0)
67 , columnNumber(0)
68 , m_controller(controller)
69 , m_outerState(controller->m_globalScopeExecutionState)
70 {
71 m_controller->m_globalScopeExecutionState = this;
72 }
73
74 ~WorkerGlobalScopeExecutionState()
75 {
76 m_controller->m_globalScopeExecutionState = m_outerState;
77 }
78
79 void trace(Visitor* visitor)
80 {
81 visitor->trace(m_errorEventFromImportedScript);
82 }
83
84 bool hadException;
85 String errorMessage;
86 int lineNumber;
87 int columnNumber;
88 String sourceURL;
89 ScriptValue exception;
90 RefPtrWillBeMember<ErrorEvent> m_errorEventFromImportedScript;
91
92 // A WorkerGlobalScopeExecutionState context is stack allocated by
93 // WorkerScriptController::evaluate(), with the contoller using it
94 // during script evaluation. To handle nested evaluate() uses,
95 // WorkerGlobalScopeExecutionStates are chained together;
96 // |m_outerState| keeps a pointer to the context object one level out
97 // (or 0, if outermost.) Upon return from evaluate(), the
98 // WorkerScriptController's WorkerGlobalScopeExecutionState is popped
99 // and the previous one restored (see above dtor.)
100 //
101 // With Oilpan, |m_outerState| isn't traced. It'll be "up the stack"
102 // and its fields will be traced when scanning the stack.
103 WorkerScriptController* m_controller;
104 WorkerGlobalScopeExecutionState* m_outerState;
105 };
106
61 WorkerScriptController::WorkerScriptController(WorkerGlobalScope& workerGlobalSc ope) 107 WorkerScriptController::WorkerScriptController(WorkerGlobalScope& workerGlobalSc ope)
62 : m_isolate(v8::Isolate::New()) 108 : m_isolate(v8::Isolate::New())
63 , m_workerGlobalScope(workerGlobalScope) 109 , m_workerGlobalScope(workerGlobalScope)
64 , m_executionForbidden(false) 110 , m_executionForbidden(false)
65 , m_executionScheduledToTerminate(false) 111 , m_executionScheduledToTerminate(false)
112 , m_globalScopeExecutionState(0)
66 { 113 {
67 m_isolate->Enter(); 114 m_isolate->Enter();
68 V8Initializer::initializeWorker(m_isolate); 115 V8Initializer::initializeWorker(m_isolate);
69 v8::V8::Initialize(); 116 v8::V8::Initialize();
70 V8PerIsolateData::ensureInitialized(m_isolate); 117 V8PerIsolateData::ensureInitialized(m_isolate);
71 m_world = DOMWrapperWorld::create(WorkerWorldId); 118 m_world = DOMWrapperWorld::create(WorkerWorldId);
72 m_interruptor = adoptPtr(new V8IsolateInterruptor(m_isolate)); 119 m_interruptor = adoptPtr(new V8IsolateInterruptor(m_isolate));
73 ThreadState::current()->addInterruptor(m_interruptor.get()); 120 ThreadState::current()->addInterruptor(m_interruptor.get());
74 } 121 }
75 122
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 193
147 V8DOMWrapper::associateObjectWithWrapper<V8WorkerGlobalScope>(PassRefPtrWill BeRawPtr<WorkerGlobalScope>(&m_workerGlobalScope), contextType, jsWorkerGlobalSc ope, m_isolate, WrapperConfiguration::Dependent); 194 V8DOMWrapper::associateObjectWithWrapper<V8WorkerGlobalScope>(PassRefPtrWill BeRawPtr<WorkerGlobalScope>(&m_workerGlobalScope), contextType, jsWorkerGlobalSc ope, m_isolate, WrapperConfiguration::Dependent);
148 195
149 // Insert the object instance as the prototype of the shadow object. 196 // Insert the object instance as the prototype of the shadow object.
150 v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_scriptS tate->context()->Global()->GetPrototype()); 197 v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_scriptS tate->context()->Global()->GetPrototype());
151 globalObject->SetPrototype(jsWorkerGlobalScope); 198 globalObject->SetPrototype(jsWorkerGlobalScope);
152 199
153 return true; 200 return true;
154 } 201 }
155 202
156 ScriptValue WorkerScriptController::evaluate(const String& script, const String& fileName, const TextPosition& scriptStartPosition, WorkerGlobalScopeExecutionSt ate* state) 203 ScriptValue WorkerScriptController::evaluate(const String& script, const String& fileName, const TextPosition& scriptStartPosition)
157 { 204 {
158 if (!initializeContextIfNeeded()) 205 if (!initializeContextIfNeeded())
159 return ScriptValue(); 206 return ScriptValue();
160 207
161 ScriptState::Scope scope(m_scriptState.get()); 208 ScriptState::Scope scope(m_scriptState.get());
162 209
163 if (!m_disableEvalPending.isEmpty()) { 210 if (!m_disableEvalPending.isEmpty()) {
164 m_scriptState->context()->AllowCodeGenerationFromStrings(false); 211 m_scriptState->context()->AllowCodeGenerationFromStrings(false);
165 m_scriptState->context()->SetErrorMessageForCodeGenerationFromStrings(v8 String(m_isolate, m_disableEvalPending)); 212 m_scriptState->context()->SetErrorMessageForCodeGenerationFromStrings(v8 String(m_isolate, m_disableEvalPending));
166 m_disableEvalPending = String(); 213 m_disableEvalPending = String();
167 } 214 }
168 215
169 v8::TryCatch block; 216 v8::TryCatch block;
170 217
171 v8::Handle<v8::String> scriptString = v8String(m_isolate, script); 218 v8::Handle<v8::String> scriptString = v8String(m_isolate, script);
172 v8::Handle<v8::Script> compiledScript = V8ScriptRunner::compileScript(script String, fileName, scriptStartPosition, 0, m_isolate); 219 v8::Handle<v8::Script> compiledScript = V8ScriptRunner::compileScript(script String, fileName, scriptStartPosition, 0, m_isolate);
173 v8::Local<v8::Value> result = V8ScriptRunner::runCompiledScript(compiledScri pt, &m_workerGlobalScope, m_isolate); 220 v8::Local<v8::Value> result = V8ScriptRunner::runCompiledScript(compiledScri pt, &m_workerGlobalScope, m_isolate);
174 221
175 if (!block.CanContinue()) { 222 if (!block.CanContinue()) {
176 m_workerGlobalScope.script()->forbidExecution(); 223 m_workerGlobalScope.script()->forbidExecution();
177 return ScriptValue(); 224 return ScriptValue();
178 } 225 }
179 226
180 if (block.HasCaught()) { 227 if (block.HasCaught()) {
181 v8::Local<v8::Message> message = block.Message(); 228 v8::Local<v8::Message> message = block.Message();
182 state->hadException = true; 229 m_globalScopeExecutionState->hadException = true;
183 state->errorMessage = toCoreString(message->Get()); 230 m_globalScopeExecutionState->errorMessage = toCoreString(message->Get()) ;
184 state->lineNumber = message->GetLineNumber(); 231 m_globalScopeExecutionState->lineNumber = message->GetLineNumber();
185 state->columnNumber = message->GetStartColumn() + 1; 232 m_globalScopeExecutionState->columnNumber = message->GetStartColumn() + 1;
186 TOSTRING_DEFAULT(V8StringResource<>, sourceURL, message->GetScriptOrigin ().ResourceName(), ScriptValue()); 233 TOSTRING_DEFAULT(V8StringResource<>, sourceURL, message->GetScriptOrigin ().ResourceName(), ScriptValue());
187 state->sourceURL = sourceURL; 234 m_globalScopeExecutionState->sourceURL = sourceURL;
188 state->exception = ScriptValue(m_scriptState.get(), block.Exception()); 235 m_globalScopeExecutionState->exception = ScriptValue(m_scriptState.get() , block.Exception());
189 block.Reset(); 236 block.Reset();
190 } else { 237 } else {
191 state->hadException = false; 238 m_globalScopeExecutionState->hadException = false;
192 } 239 }
193 240
194 if (result.IsEmpty() || result->IsUndefined()) 241 if (result.IsEmpty() || result->IsUndefined())
195 return ScriptValue(); 242 return ScriptValue();
196 243
197 return ScriptValue(m_scriptState.get(), result); 244 return ScriptValue(m_scriptState.get(), result);
198 } 245 }
199 246
200 void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, RefPtr WillBeRawPtr<ErrorEvent>* errorEvent) 247 void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, RefPtr WillBeRawPtr<ErrorEvent>* errorEvent)
201 { 248 {
202 if (isExecutionForbidden()) 249 if (isExecutionForbidden())
203 return; 250 return;
204 251
205 WorkerGlobalScopeExecutionState state; 252 WorkerGlobalScopeExecutionState state(this);
206 evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startPos ition(), &state); 253 evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startPos ition());
207 if (state.hadException) { 254 if (state.hadException) {
208 if (errorEvent) { 255 if (errorEvent) {
209 *errorEvent = m_workerGlobalScope.shouldSanitizeScriptError(state.so urceURL, NotSharableCrossOrigin) ? 256 if (state.m_errorEventFromImportedScript) {
210 ErrorEvent::createSanitizedError(m_world.get()) : ErrorEvent::cr eate(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, m_world.get()); 257 // Propagate inner error event outwards.
258 *errorEvent = state.m_errorEventFromImportedScript.release();
259 return;
260 }
261 if (m_workerGlobalScope.shouldSanitizeScriptError(state.sourceURL, N otSharableCrossOrigin))
262 *errorEvent = ErrorEvent::createSanitizedError(m_world.get());
263 else
264 *errorEvent = ErrorEvent::create(state.errorMessage, state.sourc eURL, state.lineNumber, state.columnNumber, m_world.get());
211 V8ErrorHandler::storeExceptionOnErrorEventWrapper(errorEvent->get(), state.exception.v8Value(), m_scriptState->context()->Global(), m_isolate); 265 V8ErrorHandler::storeExceptionOnErrorEventWrapper(errorEvent->get(), state.exception.v8Value(), m_scriptState->context()->Global(), m_isolate);
212 } else { 266 } else {
213 ASSERT(!m_workerGlobalScope.shouldSanitizeScriptError(state.sourceUR L, NotSharableCrossOrigin)); 267 ASSERT(!m_workerGlobalScope.shouldSanitizeScriptError(state.sourceUR L, NotSharableCrossOrigin));
214 RefPtrWillBeRawPtr<ErrorEvent> event = nullptr; 268 RefPtrWillBeRawPtr<ErrorEvent> event = nullptr;
215 if (m_errorEventFromImportedScript) { 269 if (state.m_errorEventFromImportedScript)
216 event = m_errorEventFromImportedScript.release(); 270 event = state.m_errorEventFromImportedScript.release();
217 } else { 271 else
218 event = ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, m_world.get()); 272 event = ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, m_world.get());
219 }
220 m_workerGlobalScope.reportException(event, nullptr, NotSharableCross Origin); 273 m_workerGlobalScope.reportException(event, nullptr, NotSharableCross Origin);
221 } 274 }
222 } 275 }
223 } 276 }
224 277
225 void WorkerScriptController::scheduleExecutionTermination() 278 void WorkerScriptController::scheduleExecutionTermination()
226 { 279 {
227 // The mutex provides a memory barrier to ensure that once 280 // The mutex provides a memory barrier to ensure that once
228 // termination is scheduled, isExecutionTerminating will 281 // termination is scheduled, isExecutionTerminating will
229 // accurately reflect that state when called from another thread. 282 // accurately reflect that state when called from another thread.
(...skipping 21 matching lines...) Expand all
251 { 304 {
252 ASSERT(m_workerGlobalScope.isContextThread()); 305 ASSERT(m_workerGlobalScope.isContextThread());
253 return m_executionForbidden; 306 return m_executionForbidden;
254 } 307 }
255 308
256 void WorkerScriptController::disableEval(const String& errorMessage) 309 void WorkerScriptController::disableEval(const String& errorMessage)
257 { 310 {
258 m_disableEvalPending = errorMessage; 311 m_disableEvalPending = errorMessage;
259 } 312 }
260 313
261 void WorkerScriptController::rethrowExceptionFromImportedScript(PassRefPtrWillBe RawPtr<ErrorEvent> errorEvent) 314 void WorkerScriptController::rethrowExceptionFromImportedScript(PassRefPtrWillBe RawPtr<ErrorEvent> errorEvent, ExceptionState& exceptionState)
262 { 315 {
263 m_errorEventFromImportedScript = errorEvent; 316 const String& errorMessage = errorEvent->message();
264 throwError(V8ThrowException::createError(v8GeneralError, m_errorEventFromImp ortedScript->message(), m_isolate), m_isolate); 317 if (m_globalScopeExecutionState)
318 m_globalScopeExecutionState->m_errorEventFromImportedScript = errorEvent ;
319 exceptionState.rethrowV8Exception(V8ThrowException::createError(v8GeneralErr or, errorMessage, m_isolate));
265 } 320 }
266 321
267 } // namespace WebCore 322 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/bindings/core/v8/WorkerScriptController.h ('k') | Source/core/workers/WorkerGlobalScope.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698