OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2009 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 | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 #include "wtf/text/WTFString.h" | 64 #include "wtf/text/WTFString.h" |
65 #include <v8-debug.h> | 65 #include <v8-debug.h> |
66 | 66 |
67 namespace blink { | 67 namespace blink { |
68 | 68 |
69 static Frame* findFrame(v8::Isolate* isolate, v8::Local<v8::Object> host, v8::Lo
cal<v8::Value> data) | 69 static Frame* findFrame(v8::Isolate* isolate, v8::Local<v8::Object> host, v8::Lo
cal<v8::Value> data) |
70 { | 70 { |
71 const WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data); | 71 const WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data); |
72 | 72 |
73 if (V8Window::wrapperTypeInfo.equals(type)) { | 73 if (V8Window::wrapperTypeInfo.equals(type)) { |
74 v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototype
Chain(host, isolate); | 74 v8::Local<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeC
hain(host, isolate); |
75 if (windowWrapper.IsEmpty()) | 75 if (windowWrapper.IsEmpty()) |
76 return 0; | 76 return 0; |
77 return V8Window::toImpl(windowWrapper)->frame(); | 77 return V8Window::toImpl(windowWrapper)->frame(); |
78 } | 78 } |
79 | 79 |
80 if (V8History::wrapperTypeInfo.equals(type)) | 80 if (V8History::wrapperTypeInfo.equals(type)) |
81 return V8History::toImpl(host)->frame(); | 81 return V8History::toImpl(host)->frame(); |
82 | 82 |
83 if (V8Location::wrapperTypeInfo.equals(type)) | 83 if (V8Location::wrapperTypeInfo.equals(type)) |
84 return V8Location::toImpl(host)->frame(); | 84 return V8Location::toImpl(host)->frame(); |
85 | 85 |
86 // This function can handle only those types listed above. | 86 // This function can handle only those types listed above. |
87 ASSERT_NOT_REACHED(); | 87 ASSERT_NOT_REACHED(); |
88 return 0; | 88 return 0; |
89 } | 89 } |
90 | 90 |
91 static void reportFatalErrorInMainThread(const char* location, const char* messa
ge) | 91 static void reportFatalErrorInMainThread(const char* location, const char* messa
ge) |
92 { | 92 { |
93 int memoryUsageMB = blink::Platform::current()->actualMemoryUsageMB(); | 93 int memoryUsageMB = blink::Platform::current()->actualMemoryUsageMB(); |
94 printf("V8 error: %s (%s). Current memory usage: %d MB\n", message, locatio
n, memoryUsageMB); | 94 printf("V8 error: %s (%s). Current memory usage: %d MB\n", message, locatio
n, memoryUsageMB); |
95 CRASH(); | 95 CRASH(); |
96 } | 96 } |
97 | 97 |
98 static PassRefPtrWillBeRawPtr<ScriptCallStack> extractCallStack(v8::Isolate* iso
late, v8::Handle<v8::Message> message, int* const scriptId) | 98 static PassRefPtrWillBeRawPtr<ScriptCallStack> extractCallStack(v8::Isolate* iso
late, v8::Local<v8::Message> message, int* const scriptId) |
99 { | 99 { |
100 v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace(); | 100 v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace(); |
101 RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; | 101 RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; |
102 *scriptId = message->GetScriptOrigin().ScriptID()->Value(); | 102 *scriptId = message->GetScriptOrigin().ScriptID()->Value(); |
103 // Currently stack trace is only collected when inspector is open. | 103 // Currently stack trace is only collected when inspector is open. |
104 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) { | 104 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) { |
105 callStack = createScriptCallStack(isolate, stackTrace, ScriptCallStack::
maxCallStackSizeToCapture); | 105 callStack = createScriptCallStack(isolate, stackTrace, ScriptCallStack::
maxCallStackSizeToCapture); |
106 bool success = false; | 106 bool success = false; |
107 int topScriptId = callStack->at(0).scriptId().toInt(&success); | 107 int topScriptId = callStack->at(0).scriptId().toInt(&success); |
108 if (success && topScriptId == *scriptId) | 108 if (success && topScriptId == *scriptId) |
109 *scriptId = 0; | 109 *scriptId = 0; |
110 } else { | 110 } else { |
111 Vector<ScriptCallFrame> callFrames; | 111 Vector<ScriptCallFrame> callFrames; |
112 callStack = ScriptCallStack::create(callFrames); | 112 callStack = ScriptCallStack::create(callFrames); |
113 } | 113 } |
114 return callStack.release(); | 114 return callStack.release(); |
115 } | 115 } |
116 | 116 |
117 static String extractResourceName(v8::Handle<v8::Message> message, const Documen
t* document) | 117 static String extractResourceName(v8::Local<v8::Message> message, const Document
* document) |
118 { | 118 { |
119 v8::Handle<v8::Value> resourceName = message->GetScriptOrigin().ResourceName
(); | 119 v8::Local<v8::Value> resourceName = message->GetScriptOrigin().ResourceName(
); |
120 bool shouldUseDocumentURL = document && (resourceName.IsEmpty() || !resource
Name->IsString()); | 120 bool shouldUseDocumentURL = document && (resourceName.IsEmpty() || !resource
Name->IsString()); |
121 return shouldUseDocumentURL ? document->url() : toCoreString(resourceName.As
<v8::String>()); | 121 return shouldUseDocumentURL ? document->url() : toCoreString(resourceName.As
<v8::String>()); |
122 } | 122 } |
123 | 123 |
124 static String extractMessageForConsole(v8::Isolate* isolate, v8::Handle<v8::Valu
e> data) | 124 static String extractMessageForConsole(v8::Isolate* isolate, v8::Local<v8::Value
> data) |
125 { | 125 { |
126 if (V8DOMWrapper::isWrapper(isolate, data)) { | 126 if (V8DOMWrapper::isWrapper(isolate, data)) { |
127 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(data); | 127 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(data); |
128 const WrapperTypeInfo* type = toWrapperTypeInfo(obj); | 128 const WrapperTypeInfo* type = toWrapperTypeInfo(obj); |
129 if (V8DOMException::wrapperTypeInfo.isSubclass(type)) { | 129 if (V8DOMException::wrapperTypeInfo.isSubclass(type)) { |
130 DOMException* exception = V8DOMException::toImpl(obj); | 130 DOMException* exception = V8DOMException::toImpl(obj); |
131 if (exception && !exception->messageForConsole().isEmpty()) | 131 if (exception && !exception->messageForConsole().isEmpty()) |
132 return exception->toStringForConsole(); | 132 return exception->toStringForConsole(); |
133 } | 133 } |
134 } | 134 } |
135 return emptyString(); | 135 return emptyString(); |
136 } | 136 } |
137 | 137 |
138 static void messageHandlerInMainThread(v8::Handle<v8::Message> message, v8::Hand
le<v8::Value> data) | 138 static void messageHandlerInMainThread(v8::Local<v8::Message> message, v8::Local
<v8::Value> data) |
139 { | 139 { |
140 ASSERT(isMainThread()); | 140 ASSERT(isMainThread()); |
141 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 141 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
142 // If called during context initialization, there will be no entered window. | 142 // If called during context initialization, there will be no entered window. |
143 LocalDOMWindow* enteredWindow = enteredDOMWindow(isolate); | 143 LocalDOMWindow* enteredWindow = enteredDOMWindow(isolate); |
144 if (!enteredWindow || !enteredWindow->isCurrentlyDisplayedInFrame()) | 144 if (!enteredWindow || !enteredWindow->isCurrentlyDisplayedInFrame()) |
145 return; | 145 return; |
146 | 146 |
147 int scriptId = 0; | 147 int scriptId = 0; |
148 RefPtrWillBeRawPtr<ScriptCallStack> callStack = extractCallStack(isolate, me
ssage, &scriptId); | 148 RefPtrWillBeRawPtr<ScriptCallStack> callStack = extractCallStack(isolate, me
ssage, &scriptId); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data) | 203 static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data) |
204 { | 204 { |
205 ASSERT(isMainThread()); | 205 ASSERT(isMainThread()); |
206 if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { | 206 if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { |
207 rejectedPromisesOnMainThread().handlerAdded(data); | 207 rejectedPromisesOnMainThread().handlerAdded(data); |
208 return; | 208 return; |
209 } | 209 } |
210 | 210 |
211 ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); | 211 ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); |
212 | 212 |
213 v8::Handle<v8::Promise> promise = data.GetPromise(); | 213 v8::Local<v8::Promise> promise = data.GetPromise(); |
214 | 214 |
215 v8::Isolate* isolate = promise->GetIsolate(); | 215 v8::Isolate* isolate = promise->GetIsolate(); |
216 // There is no entered window during microtask callbacks from V8, | 216 // There is no entered window during microtask callbacks from V8, |
217 // thus we call toDOMWindow() instead of enteredDOMWindow(). | 217 // thus we call toDOMWindow() instead of enteredDOMWindow(). |
218 LocalDOMWindow* window = currentDOMWindow(isolate); | 218 LocalDOMWindow* window = currentDOMWindow(isolate); |
219 if (!window || !window->isCurrentlyDisplayedInFrame()) | 219 if (!window || !window->isCurrentlyDisplayedInFrame()) |
220 return; | 220 return; |
221 | 221 |
222 v8::Handle<v8::Value> exception = data.GetValue(); | 222 v8::Local<v8::Value> exception = data.GetValue(); |
223 if (V8DOMWrapper::isWrapper(isolate, exception)) { | 223 if (V8DOMWrapper::isWrapper(isolate, exception)) { |
224 // Try to get the stack & location from a wrapped exception object (e.g.
DOMException). | 224 // Try to get the stack & location from a wrapped exception object (e.g.
DOMException). |
225 ASSERT(exception->IsObject()); | 225 ASSERT(exception->IsObject()); |
226 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(exception); | 226 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(exception); |
227 v8::Handle<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj
, V8HiddenValue::error(isolate)); | 227 v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj,
V8HiddenValue::error(isolate)); |
228 if (!error.IsEmpty()) | 228 if (!error.IsEmpty()) |
229 exception = error; | 229 exception = error; |
230 } | 230 } |
231 | 231 |
232 int scriptId = 0; | 232 int scriptId = 0; |
233 int lineNumber = 0; | 233 int lineNumber = 0; |
234 int columnNumber = 0; | 234 int columnNumber = 0; |
235 String resourceName; | 235 String resourceName; |
236 String errorMessage; | 236 String errorMessage; |
237 RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; | 237 RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; |
238 | 238 |
239 v8::Handle<v8::Message> message = v8::Exception::CreateMessage(exception); | 239 v8::Local<v8::Message> message = v8::Exception::CreateMessage(exception); |
240 if (!message.IsEmpty()) { | 240 if (!message.IsEmpty()) { |
241 if (v8Call(message->GetLineNumber(isolate->GetCurrentContext()), lineNum
ber) | 241 if (v8Call(message->GetLineNumber(isolate->GetCurrentContext()), lineNum
ber) |
242 && v8Call(message->GetStartColumn(isolate->GetCurrentContext()), col
umnNumber)) | 242 && v8Call(message->GetStartColumn(isolate->GetCurrentContext()), col
umnNumber)) |
243 ++columnNumber; | 243 ++columnNumber; |
244 resourceName = extractResourceName(message, window->document()); | 244 resourceName = extractResourceName(message, window->document()); |
245 errorMessage = toCoreStringWithNullCheck(message->Get()); | 245 errorMessage = toCoreStringWithNullCheck(message->Get()); |
246 callStack = extractCallStack(isolate, message, &scriptId); | 246 callStack = extractCallStack(isolate, message, &scriptId); |
247 } else if (!exception.IsEmpty() && exception->IsInt32()) { | 247 } else if (!exception.IsEmpty() && exception->IsInt32()) { |
248 // For Smi's the message would be empty. | 248 // For Smi's the message would be empty. |
249 errorMessage = "Uncaught " + String::number(exception.As<v8::Integer>()-
>Value()); | 249 errorMessage = "Uncaught " + String::number(exception.As<v8::Integer>()-
>Value()); |
250 } | 250 } |
251 | 251 |
252 String messageForConsole = extractMessageForConsole(isolate, data.GetValue()
); | 252 String messageForConsole = extractMessageForConsole(isolate, data.GetValue()
); |
253 if (!messageForConsole.isEmpty()) | 253 if (!messageForConsole.isEmpty()) |
254 errorMessage = "Uncaught " + messageForConsole; | 254 errorMessage = "Uncaught " + messageForConsole; |
255 | 255 |
256 ScriptState* scriptState = ScriptState::current(isolate); | 256 ScriptState* scriptState = ScriptState::current(isolate); |
257 rejectedPromisesOnMainThread().rejectedWithNoHandler(scriptState, data, erro
rMessage, resourceName, scriptId, lineNumber, columnNumber, callStack); | 257 rejectedPromisesOnMainThread().rejectedWithNoHandler(scriptState, data, erro
rMessage, resourceName, scriptId, lineNumber, columnNumber, callStack); |
258 } | 258 } |
259 | 259 |
260 static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage data) | 260 static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage data) |
261 { | 261 { |
262 v8::Handle<v8::Promise> promise = data.GetPromise(); | 262 v8::Local<v8::Promise> promise = data.GetPromise(); |
263 | 263 |
264 // Bail out if called during context initialization. | 264 // Bail out if called during context initialization. |
265 v8::Isolate* isolate = promise->GetIsolate(); | 265 v8::Isolate* isolate = promise->GetIsolate(); |
266 ScriptState* scriptState = ScriptState::current(isolate); | 266 ScriptState* scriptState = ScriptState::current(isolate); |
267 if (!scriptState->contextIsValid()) | 267 if (!scriptState->contextIsValid()) |
268 return; | 268 return; |
269 | 269 |
270 ExecutionContext* executionContext = scriptState->executionContext(); | 270 ExecutionContext* executionContext = scriptState->executionContext(); |
271 if (!executionContext) | 271 if (!executionContext) |
272 return; | 272 return; |
273 | 273 |
274 ASSERT(executionContext->isWorkerGlobalScope()); | 274 ASSERT(executionContext->isWorkerGlobalScope()); |
275 WorkerScriptController* scriptController = toWorkerGlobalScope(executionCont
ext)->script(); | 275 WorkerScriptController* scriptController = toWorkerGlobalScope(executionCont
ext)->script(); |
276 ASSERT(scriptController); | 276 ASSERT(scriptController); |
277 | 277 |
278 if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { | 278 if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { |
279 scriptController->rejectedPromises()->handlerAdded(data); | 279 scriptController->rejectedPromises()->handlerAdded(data); |
280 return; | 280 return; |
281 } | 281 } |
282 | 282 |
283 ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); | 283 ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); |
284 | 284 |
285 int scriptId = 0; | 285 int scriptId = 0; |
286 int lineNumber = 0; | 286 int lineNumber = 0; |
287 int columnNumber = 0; | 287 int columnNumber = 0; |
288 String resourceName; | 288 String resourceName; |
289 String errorMessage; | 289 String errorMessage; |
290 | 290 |
291 v8::Handle<v8::Message> message = v8::Exception::CreateMessage(data.GetValue
()); | 291 v8::Local<v8::Message> message = v8::Exception::CreateMessage(data.GetValue(
)); |
292 if (!message.IsEmpty()) { | 292 if (!message.IsEmpty()) { |
293 TOSTRING_VOID(V8StringResource<>, resourceName, message->GetScriptOrigin
().ResourceName()); | 293 TOSTRING_VOID(V8StringResource<>, resourceName, message->GetScriptOrigin
().ResourceName()); |
294 scriptId = message->GetScriptOrigin().ScriptID()->Value(); | 294 scriptId = message->GetScriptOrigin().ScriptID()->Value(); |
295 if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber) | 295 if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber) |
296 && v8Call(message->GetStartColumn(scriptState->context()), columnNum
ber)) | 296 && v8Call(message->GetStartColumn(scriptState->context()), columnNum
ber)) |
297 ++columnNumber; | 297 ++columnNumber; |
298 // message->Get() can be empty here. https://crbug.com/450330 | 298 // message->Get() can be empty here. https://crbug.com/450330 |
299 errorMessage = toCoreStringWithNullCheck(message->Get()); | 299 errorMessage = toCoreStringWithNullCheck(message->Get()); |
300 } | 300 } |
301 scriptController->rejectedPromises()->rejectedWithNoHandler(scriptState, dat
a, errorMessage, resourceName, scriptId, lineNumber, columnNumber, nullptr); | 301 scriptController->rejectedPromises()->rejectedWithNoHandler(scriptState, dat
a, errorMessage, resourceName, scriptId, lineNumber, columnNumber, nullptr); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 | 414 |
415 ScriptProfiler::initialize(); | 415 ScriptProfiler::initialize(); |
416 } | 416 } |
417 | 417 |
418 static void reportFatalErrorInWorker(const char* location, const char* message) | 418 static void reportFatalErrorInWorker(const char* location, const char* message) |
419 { | 419 { |
420 // FIXME: We temporarily deal with V8 internal error situations such as out-
of-memory by crashing the worker. | 420 // FIXME: We temporarily deal with V8 internal error situations such as out-
of-memory by crashing the worker. |
421 CRASH(); | 421 CRASH(); |
422 } | 422 } |
423 | 423 |
424 static void messageHandlerInWorker(v8::Handle<v8::Message> message, v8::Handle<v
8::Value> data) | 424 static void messageHandlerInWorker(v8::Local<v8::Message> message, v8::Local<v8:
:Value> data) |
425 { | 425 { |
426 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 426 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
427 V8PerIsolateData* perIsolateData = V8PerIsolateData::from(isolate); | 427 V8PerIsolateData* perIsolateData = V8PerIsolateData::from(isolate); |
428 // Exceptions that occur in error handler should be ignored since in that ca
se | 428 // Exceptions that occur in error handler should be ignored since in that ca
se |
429 // WorkerGlobalScope::reportException will send the exception to the worker
object. | 429 // WorkerGlobalScope::reportException will send the exception to the worker
object. |
430 if (perIsolateData->isReportingException()) | 430 if (perIsolateData->isReportingException()) |
431 return; | 431 return; |
432 perIsolateData->setReportingException(true); | 432 perIsolateData->setReportingException(true); |
433 | 433 |
434 ScriptState* scriptState = ScriptState::current(isolate); | 434 ScriptState* scriptState = ScriptState::current(isolate); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 | 470 |
471 v8::V8::AddMessageListener(messageHandlerInWorker); | 471 v8::V8::AddMessageListener(messageHandlerInWorker); |
472 v8::V8::SetFatalErrorHandler(reportFatalErrorInWorker); | 472 v8::V8::SetFatalErrorHandler(reportFatalErrorInWorker); |
473 | 473 |
474 uint32_t here; | 474 uint32_t here; |
475 isolate->SetStackLimit(reinterpret_cast<uintptr_t>(&here - kWorkerMaxStackSi
ze / sizeof(uint32_t*))); | 475 isolate->SetStackLimit(reinterpret_cast<uintptr_t>(&here - kWorkerMaxStackSi
ze / sizeof(uint32_t*))); |
476 isolate->SetPromiseRejectCallback(promiseRejectHandlerInWorker); | 476 isolate->SetPromiseRejectCallback(promiseRejectHandlerInWorker); |
477 } | 477 } |
478 | 478 |
479 } // namespace blink | 479 } // namespace blink |
OLD | NEW |