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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 return 0; | 83 return 0; |
84 } | 84 } |
85 | 85 |
86 static void reportFatalErrorInMainThread(const char* location, const char* messa ge) | 86 static void reportFatalErrorInMainThread(const char* location, const char* messa ge) |
87 { | 87 { |
88 int memoryUsageMB = blink::Platform::current()->actualMemoryUsageMB(); | 88 int memoryUsageMB = blink::Platform::current()->actualMemoryUsageMB(); |
89 printf("V8 error: %s (%s). Current memory usage: %d MB\n", message, locatio n, memoryUsageMB); | 89 printf("V8 error: %s (%s). Current memory usage: %d MB\n", message, locatio n, memoryUsageMB); |
90 CRASH(); | 90 CRASH(); |
91 } | 91 } |
92 | 92 |
93 static PassRefPtrWillBeRawPtr<ScriptCallStack> extractCallStack(v8::Isolate* iso late, v8::Handle<v8::Message> message, int* const scriptId) | |
94 { | |
95 v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace(); | |
96 RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; | |
97 *scriptId = message->GetScriptOrigin().ScriptID()->Value(); | |
98 // Currently stack trace is only collected when inspector is open. | |
99 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) { | |
100 callStack = createScriptCallStack(isolate, stackTrace, ScriptCallStack:: maxCallStackSizeToCapture); | |
101 bool success = false; | |
102 int topScriptId = callStack->at(0).scriptId().toInt(&success); | |
103 if (success && topScriptId == *scriptId) | |
104 *scriptId = 0; | |
105 } else { | |
106 Vector<ScriptCallFrame> callFrames; | |
107 callStack = ScriptCallStack::create(callFrames); | |
108 } | |
109 return callStack.release(); | |
110 } | |
111 | |
112 static String extractResourceName(v8::Handle<v8::Message> message, const Documen t* document) | |
113 { | |
114 v8::Handle<v8::Value> resourceName = message->GetScriptOrigin().ResourceName (); | |
115 bool shouldUseDocumentURL = document && (resourceName.IsEmpty() || !resource Name->IsString()); | |
116 return shouldUseDocumentURL ? document->url() : toCoreString(resourceName.As <v8::String>()); | |
117 } | |
118 | |
93 static void messageHandlerInMainThread(v8::Handle<v8::Message> message, v8::Hand le<v8::Value> data) | 119 static void messageHandlerInMainThread(v8::Handle<v8::Message> message, v8::Hand le<v8::Value> data) |
94 { | 120 { |
95 ASSERT(isMainThread()); | 121 ASSERT(isMainThread()); |
96 // It's possible that messageHandlerInMainThread() is invoked while we're in itializing a window. | 122 // It's possible that messageHandlerInMainThread() is invoked while we're in itializing a window. |
97 // In that half-baked situation, we don't have a valid context nor a valid w orld, | 123 // In that half-baked situation, we don't have a valid context nor a valid w orld, |
98 // so just return immediately. | 124 // so just return immediately. |
99 if (DOMWrapperWorld::windowIsBeingInitialized()) | 125 if (DOMWrapperWorld::windowIsBeingInitialized()) |
100 return; | 126 return; |
101 | 127 |
102 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 128 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
103 // If called during context initialization, there will be no entered window. | 129 // If called during context initialization, there will be no entered window. |
104 LocalDOMWindow* enteredWindow = enteredDOMWindow(isolate); | 130 LocalDOMWindow* enteredWindow = enteredDOMWindow(isolate); |
105 if (!enteredWindow || !enteredWindow->isCurrentlyDisplayedInFrame()) | 131 if (!enteredWindow || !enteredWindow->isCurrentlyDisplayedInFrame()) |
106 return; | 132 return; |
107 | 133 |
108 String errorMessage = toCoreString(message->Get()); | 134 int scriptId = 0; |
109 | 135 RefPtrWillBeRawPtr<ScriptCallStack> callStack = extractCallStack(isolate, me ssage, &scriptId); |
110 v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace(); | 136 String resourceName = extractResourceName(message, enteredWindow->document() ); |
111 RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; | |
112 int scriptId = message->GetScriptOrigin().ScriptID()->Value(); | |
113 // Currently stack trace is only collected when inspector is open. | |
114 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) { | |
115 callStack = createScriptCallStack(isolate, stackTrace, ScriptCallStack:: maxCallStackSizeToCapture); | |
116 bool success = false; | |
117 int topScriptId = callStack->at(0).scriptId().toInt(&success); | |
118 if (success && topScriptId == scriptId) | |
119 scriptId = 0; | |
120 } else { | |
121 Vector<ScriptCallFrame> callFrames; | |
122 callStack = ScriptCallStack::create(callFrames); | |
123 } | |
124 | |
125 v8::Handle<v8::Value> resourceName = message->GetScriptOrigin().ResourceName (); | |
126 bool shouldUseDocumentURL = resourceName.IsEmpty() || !resourceName->IsStrin g(); | |
127 String resource = shouldUseDocumentURL ? enteredWindow->document()->url() : toCoreString(resourceName.As<v8::String>()); | |
128 AccessControlStatus corsStatus = message->IsSharedCrossOrigin() ? SharableCr ossOrigin : NotSharableCrossOrigin; | 137 AccessControlStatus corsStatus = message->IsSharedCrossOrigin() ? SharableCr ossOrigin : NotSharableCrossOrigin; |
129 | 138 |
130 ScriptState* scriptState = ScriptState::current(isolate); | 139 ScriptState* scriptState = ScriptState::current(isolate); |
131 RefPtrWillBeRawPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, reso urce, message->GetLineNumber(), message->GetStartColumn() + 1, &scriptState->wor ld()); | 140 String errorMessage = toCoreString(message->Get()); |
141 RefPtrWillBeRawPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, reso urceName, message->GetLineNumber(), message->GetStartColumn() + 1, &scriptState- >world()); | |
132 if (V8DOMWrapper::isDOMWrapper(data)) { | 142 if (V8DOMWrapper::isDOMWrapper(data)) { |
133 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(data); | 143 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(data); |
134 const WrapperTypeInfo* type = toWrapperTypeInfo(obj); | 144 const WrapperTypeInfo* type = toWrapperTypeInfo(obj); |
135 if (V8DOMException::wrapperTypeInfo.isSubclass(type)) { | 145 if (V8DOMException::wrapperTypeInfo.isSubclass(type)) { |
136 DOMException* exception = V8DOMException::toImpl(obj); | 146 DOMException* exception = V8DOMException::toImpl(obj); |
137 if (exception && !exception->messageForConsole().isEmpty()) | 147 if (exception && !exception->messageForConsole().isEmpty()) |
138 event->setUnsanitizedMessage("Uncaught " + exception->toStringFo rConsole()); | 148 event->setUnsanitizedMessage("Uncaught " + exception->toStringFo rConsole()); |
139 } | 149 } |
140 } | 150 } |
141 | 151 |
(...skipping 17 matching lines...) Expand all Loading... | |
159 } else { | 169 } else { |
160 enteredWindow->document()->reportException(event.release(), scriptId, ca llStack, corsStatus); | 170 enteredWindow->document()->reportException(event.release(), scriptId, ca llStack, corsStatus); |
161 } | 171 } |
162 } | 172 } |
163 | 173 |
164 namespace { | 174 namespace { |
165 | 175 |
166 class PromiseRejectMessage { | 176 class PromiseRejectMessage { |
167 ALLOW_ONLY_INLINE_ALLOCATION(); | 177 ALLOW_ONLY_INLINE_ALLOCATION(); |
168 public: | 178 public: |
169 PromiseRejectMessage(const ScriptValue& promise, PassRefPtrWillBeRawPtr<Scri ptCallStack> callStack) | 179 PromiseRejectMessage(const ScriptValue& promise, const String& resourceName, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCa llStack> callStack) |
170 : m_promise(promise) | 180 : m_promise(promise) |
181 , m_resourceName(resourceName) | |
182 , m_scriptId(scriptId) | |
183 , m_lineNumber(lineNumber) | |
184 , m_columnNumber(columnNumber) | |
171 , m_callStack(callStack) | 185 , m_callStack(callStack) |
172 { | 186 { |
173 } | 187 } |
174 | 188 |
175 void trace(Visitor* visitor) | 189 void trace(Visitor* visitor) |
176 { | 190 { |
177 visitor->trace(m_callStack); | 191 visitor->trace(m_callStack); |
178 } | 192 } |
179 | 193 |
180 const ScriptValue m_promise; | 194 const ScriptValue m_promise; |
195 const String m_resourceName; | |
196 const int m_scriptId; | |
197 const int m_lineNumber; | |
198 const int m_columnNumber; | |
181 const RefPtrWillBeMember<ScriptCallStack> m_callStack; | 199 const RefPtrWillBeMember<ScriptCallStack> m_callStack; |
182 }; | 200 }; |
183 | 201 |
184 } // namespace | 202 } // namespace |
185 | 203 |
186 typedef Deque<PromiseRejectMessage> PromiseRejectMessageQueue; | 204 typedef Deque<PromiseRejectMessage> PromiseRejectMessageQueue; |
187 | 205 |
188 static PromiseRejectMessageQueue& promiseRejectMessageQueue() | 206 static PromiseRejectMessageQueue& promiseRejectMessageQueue() |
189 { | 207 { |
190 AtomicallyInitializedStatic(ThreadSpecific<PromiseRejectMessageQueue>*, queu e = new ThreadSpecific<PromiseRejectMessageQueue>); | 208 AtomicallyInitializedStatic(ThreadSpecific<PromiseRejectMessageQueue>*, queu e = new ThreadSpecific<PromiseRejectMessageQueue>); |
(...skipping 22 matching lines...) Expand all Loading... | |
213 ASSERT(!value.IsEmpty() && value->IsPromise()); | 231 ASSERT(!value.IsEmpty() && value->IsPromise()); |
214 if (v8::Handle<v8::Promise>::Cast(value)->HasHandler()) | 232 if (v8::Handle<v8::Promise>::Cast(value)->HasHandler()) |
215 continue; | 233 continue; |
216 | 234 |
217 const String errorMessage = "Unhandled promise rejection"; | 235 const String errorMessage = "Unhandled promise rejection"; |
218 Vector<ScriptValue> args; | 236 Vector<ScriptValue> args; |
219 args.append(ScriptValue(scriptState, v8String(scriptState->isolate(), er rorMessage))); | 237 args.append(ScriptValue(scriptState, v8String(scriptState->isolate(), er rorMessage))); |
220 args.append(message.m_promise); | 238 args.append(message.m_promise); |
221 RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::create( scriptState, args); | 239 RefPtrWillBeRawPtr<ScriptArguments> arguments = ScriptArguments::create( scriptState, args); |
222 | 240 |
223 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::crea te(JSMessageSource, ErrorMessageLevel, errorMessage); | 241 RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::crea te(JSMessageSource, ErrorMessageLevel, errorMessage, message.m_resourceName, mes sage.m_lineNumber, message.m_columnNumber); |
224 consoleMessage->setScriptArguments(arguments); | 242 consoleMessage->setScriptArguments(arguments); |
225 consoleMessage->setCallStack(message.m_callStack); | 243 consoleMessage->setCallStack(message.m_callStack); |
244 consoleMessage->setScriptId(message.m_scriptId); | |
226 executionContext->addConsoleMessage(consoleMessage.release()); | 245 executionContext->addConsoleMessage(consoleMessage.release()); |
227 } | 246 } |
228 } | 247 } |
229 | 248 |
230 static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage message) | 249 static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data) |
231 { | 250 { |
232 ASSERT(isMainThread()); | 251 ASSERT(isMainThread()); |
233 | 252 |
234 if (message.GetEvent() != v8::kPromiseRejectWithNoHandler) | 253 if (data.GetEvent() != v8::kPromiseRejectWithNoHandler) |
235 return; | 254 return; |
236 | 255 |
237 // It's possible that promiseRejectHandlerInMainThread() is invoked while we 're initializing a window. | 256 // It's possible that promiseRejectHandlerInMainThread() is invoked while we 're initializing a window. |
238 // In that half-baked situation, we don't have a valid context nor a valid w orld, | 257 // In that half-baked situation, we don't have a valid context nor a valid w orld, |
239 // so just return immediately. | 258 // so just return immediately. |
240 if (DOMWrapperWorld::windowIsBeingInitialized()) | 259 if (DOMWrapperWorld::windowIsBeingInitialized()) |
241 return; | 260 return; |
242 | 261 |
243 v8::Handle<v8::Promise> promise = message.GetPromise(); | 262 v8::Handle<v8::Promise> promise = data.GetPromise(); |
244 | 263 |
245 // Bail out if called during context initialization. | 264 // Bail out if called during context initialization. |
246 v8::Isolate* isolate = promise->GetIsolate(); | 265 v8::Isolate* isolate = promise->GetIsolate(); |
247 v8::Handle<v8::Context> context = isolate->GetCurrentContext(); | 266 v8::Handle<v8::Context> context = isolate->GetCurrentContext(); |
248 if (context.IsEmpty()) | 267 if (context.IsEmpty()) |
249 return; | 268 return; |
250 v8::Handle<v8::Value> global = V8Window::findInstanceInPrototypeChain(contex t->Global(), context->GetIsolate()); | 269 v8::Handle<v8::Value> global = V8Window::findInstanceInPrototypeChain(contex t->Global(), context->GetIsolate()); |
251 if (global.IsEmpty()) | 270 if (global.IsEmpty()) |
252 return; | 271 return; |
253 if (!toFrameIfNotDetached(context)) | 272 |
273 // There is no entered window during microtask callbacks from V8, | |
274 // thus we call toDOMWindow() instead of enteredDOMWindow(). | |
275 LocalDOMWindow* window = toLocalDOMWindow(toDOMWindow(context)); | |
276 if (!window || !window->isCurrentlyDisplayedInFrame()) | |
254 return; | 277 return; |
255 | 278 |
279 v8::Handle<v8::Value> exception = data.GetValue(); | |
280 if (V8DOMWrapper::isDOMWrapper(exception)) { | |
281 // Try to get the stack & location from a wrapped exception object (e.g. DOMException). | |
282 ASSERT(exception->IsObject()); | |
283 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(exception); | |
284 v8::Handle<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj , V8HiddenValue::error(isolate)); | |
285 if (!error.IsEmpty()) | |
286 exception = error; | |
287 } | |
288 | |
289 int scriptId = 0; | |
290 int lineNumber = 0; | |
291 int columnNumber = 0; | |
292 String resourceName; | |
256 RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; | 293 RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; |
257 v8::Handle<v8::StackTrace> stackTrace = message.GetStackTrace(); | |
258 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) | |
259 callStack = createScriptCallStack(isolate, stackTrace, ScriptCallStack:: maxCallStackSizeToCapture); | |
260 | 294 |
261 if (!callStack && V8DOMWrapper::isDOMWrapper(message.GetValue())) { | 295 v8::Handle<v8::Message> message = v8::Exception::CreateMessage(exception); |
262 // Try to get the stack from a wrapped exception object (e.g. DOMExcepti on). | 296 if (!message.IsEmpty()) { |
263 v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(message.GetVal ue()); | 297 lineNumber = message->GetLineNumber(); |
264 v8::Handle<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj , V8HiddenValue::error(isolate)); | 298 columnNumber = message->GetStartColumn() + 1; |
265 if (!error.IsEmpty()) { | 299 callStack = extractCallStack(isolate, message, &scriptId); |
266 stackTrace = v8::Exception::GetStackTrace(error); | 300 resourceName = extractResourceName(message, window->document()); |
267 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) | |
268 callStack = createScriptCallStack(isolate, stackTrace, ScriptCal lStack::maxCallStackSizeToCapture); | |
269 } | |
270 } | 301 } |
271 | 302 |
272 ScriptState* scriptState = ScriptState::from(context); | 303 ScriptState* scriptState = ScriptState::from(context); |
273 promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptSt ate, promise), callStack)); | 304 promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptSt ate, promise), resourceName, scriptId, lineNumber, columnNumber, callStack)); |
vsevik
2014/11/12 15:43:00
Please see https://code.google.com/p/chromium/issu
| |
274 } | 305 } |
275 | 306 |
276 static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage message) | 307 static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage data) |
277 { | 308 { |
278 if (message.GetEvent() != v8::kPromiseRejectWithNoHandler) | 309 if (data.GetEvent() != v8::kPromiseRejectWithNoHandler) |
279 return; | 310 return; |
280 | 311 |
281 v8::Handle<v8::Promise> promise = message.GetPromise(); | 312 v8::Handle<v8::Promise> promise = data.GetPromise(); |
282 | 313 |
283 // Bail out if called during context initialization. | 314 // Bail out if called during context initialization. |
284 v8::Isolate* isolate = promise->GetIsolate(); | 315 v8::Isolate* isolate = promise->GetIsolate(); |
285 v8::Handle<v8::Context> context = isolate->GetCurrentContext(); | 316 v8::Handle<v8::Context> context = isolate->GetCurrentContext(); |
286 if (context.IsEmpty()) | 317 if (context.IsEmpty()) |
287 return; | 318 return; |
288 | 319 |
289 RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; | 320 int scriptId = 0; |
290 v8::Handle<v8::StackTrace> stackTrace = message.GetStackTrace(); | 321 int lineNumber = 0; |
291 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) | 322 int columnNumber = 0; |
292 callStack = createScriptCallStack(isolate, stackTrace, ScriptCallStack:: maxCallStackSizeToCapture); | 323 String resourceName; |
324 | |
325 v8::Handle<v8::Message> message = v8::Exception::CreateMessage(data.GetValue ()); | |
326 if (!message.IsEmpty()) { | |
327 TOSTRING_VOID(V8StringResource<>, resourceName, message->GetScriptOrigin ().ResourceName()); | |
328 scriptId = message->GetScriptOrigin().ScriptID()->Value(); | |
329 lineNumber = message->GetLineNumber(); | |
330 columnNumber = message->GetStartColumn() + 1; | |
331 } | |
293 | 332 |
294 ScriptState* scriptState = ScriptState::from(context); | 333 ScriptState* scriptState = ScriptState::from(context); |
295 promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptSt ate, promise), callStack)); | 334 promiseRejectMessageQueue().append(PromiseRejectMessage(ScriptValue(scriptSt ate, promise), resourceName, scriptId, lineNumber, columnNumber, nullptr)); |
296 } | 335 } |
297 | 336 |
298 static void failedAccessCheckCallbackInMainThread(v8::Local<v8::Object> host, v8 ::AccessType type, v8::Local<v8::Value> data) | 337 static void failedAccessCheckCallbackInMainThread(v8::Local<v8::Object> host, v8 ::AccessType type, v8::Local<v8::Value> data) |
299 { | 338 { |
300 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 339 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
301 Frame* target = findFrame(host, data, isolate); | 340 Frame* target = findFrame(host, data, isolate); |
302 if (!target) | 341 if (!target) |
303 return; | 342 return; |
304 DOMWindow* targetWindow = target->domWindow(); | 343 DOMWindow* targetWindow = target->domWindow(); |
305 | 344 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 | 474 |
436 v8::V8::AddMessageListener(messageHandlerInWorker); | 475 v8::V8::AddMessageListener(messageHandlerInWorker); |
437 v8::V8::SetFatalErrorHandler(reportFatalErrorInWorker); | 476 v8::V8::SetFatalErrorHandler(reportFatalErrorInWorker); |
438 | 477 |
439 uint32_t here; | 478 uint32_t here; |
440 isolate->SetStackLimit(reinterpret_cast<uintptr_t>(&here - kWorkerMaxStackSi ze / sizeof(uint32_t*))); | 479 isolate->SetStackLimit(reinterpret_cast<uintptr_t>(&here - kWorkerMaxStackSi ze / sizeof(uint32_t*))); |
441 isolate->SetPromiseRejectCallback(promiseRejectHandlerInWorker); | 480 isolate->SetPromiseRejectCallback(promiseRejectHandlerInWorker); |
442 } | 481 } |
443 | 482 |
444 } // namespace blink | 483 } // namespace blink |
OLD | NEW |