| 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 |