| 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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 accessControlStatus = SharableCrossOrigin; | 146 accessControlStatus = SharableCrossOrigin; |
| 147 | 147 |
| 148 ErrorEvent* event = | 148 ErrorEvent* event = |
| 149 ErrorEvent::create(toCoreStringWithNullCheck(message->Get()), | 149 ErrorEvent::create(toCoreStringWithNullCheck(message->Get()), |
| 150 std::move(location), &scriptState->world()); | 150 std::move(location), &scriptState->world()); |
| 151 | 151 |
| 152 String messageForConsole = extractMessageForConsole(isolate, data); | 152 String messageForConsole = extractMessageForConsole(isolate, data); |
| 153 if (!messageForConsole.isEmpty()) | 153 if (!messageForConsole.isEmpty()) |
| 154 event->setUnsanitizedMessage("Uncaught " + messageForConsole); | 154 event->setUnsanitizedMessage("Uncaught " + messageForConsole); |
| 155 | 155 |
| 156 // This method might be called while we're creating a new context. In this cas
e, we | 156 // This method might be called while we're creating a new context. In this |
| 157 // avoid storing the exception object, as we can't create a wrapper during con
text creation. | 157 // case, we avoid storing the exception object, as we can't create a wrapper |
| 158 // FIXME: Can we even get here during initialization now that we bail out when
GetEntered returns an empty handle? | 158 // during context creation. |
| 159 // FIXME: Can we even get here during initialization now that we bail out when |
| 160 // GetEntered returns an empty handle? |
| 159 if (context->isDocument()) { | 161 if (context->isDocument()) { |
| 160 LocalFrame* frame = toDocument(context)->frame(); | 162 LocalFrame* frame = toDocument(context)->frame(); |
| 161 if (frame && frame->script().existingWindowProxy(scriptState->world())) { | 163 if (frame && frame->script().existingWindowProxy(scriptState->world())) { |
| 162 V8ErrorHandler::storeExceptionOnErrorEventWrapper( | 164 V8ErrorHandler::storeExceptionOnErrorEventWrapper( |
| 163 scriptState, event, data, scriptState->context()->Global()); | 165 scriptState, event, data, scriptState->context()->Global()); |
| 164 } | 166 } |
| 165 } | 167 } |
| 166 | 168 |
| 167 if (scriptState->world().isPrivateScriptIsolatedWorld()) { | 169 if (scriptState->world().isPrivateScriptIsolatedWorld()) { |
| 168 // We allow a private script to dispatch error events even in a EventDispatc
hForbiddenScope scope. | 170 // We allow a private script to dispatch error events even in a |
| 169 // Without having this ability, it's hard to debug the private script becaus
e syntax errors | 171 // EventDispatchForbiddenScope scope. Without having this ability, it's |
| 170 // in the private script are not reported to console (the private script jus
t crashes silently). | 172 // hard to debug the private script because syntax errors in the private |
| 171 // Allowing error events in private scripts is safe because error events don
't propagate to | 173 // script are not reported to console (the private script just crashes |
| 172 // other isolated worlds (which means that the error events won't fire any e
vent listeners | 174 // silently). Allowing error events in private scripts is safe because |
| 173 // in user's scripts). | 175 // error events don't propagate to other isolated worlds (which means that |
| 176 // the error events won't fire any event listeners in user's scripts). |
| 174 EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents; | 177 EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents; |
| 175 context->dispatchErrorEvent(event, accessControlStatus); | 178 context->dispatchErrorEvent(event, accessControlStatus); |
| 176 } else { | 179 } else { |
| 177 context->dispatchErrorEvent(event, accessControlStatus); | 180 context->dispatchErrorEvent(event, accessControlStatus); |
| 178 } | 181 } |
| 179 } | 182 } |
| 180 | 183 |
| 181 namespace { | 184 namespace { |
| 182 | 185 |
| 183 static RejectedPromises& rejectedPromisesOnMainThread() { | 186 static RejectedPromises& rejectedPromisesOnMainThread() { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 202 } | 205 } |
| 203 | 206 |
| 204 ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); | 207 ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); |
| 205 | 208 |
| 206 v8::Local<v8::Promise> promise = data.GetPromise(); | 209 v8::Local<v8::Promise> promise = data.GetPromise(); |
| 207 v8::Isolate* isolate = promise->GetIsolate(); | 210 v8::Isolate* isolate = promise->GetIsolate(); |
| 208 ExecutionContext* context = scriptState->getExecutionContext(); | 211 ExecutionContext* context = scriptState->getExecutionContext(); |
| 209 | 212 |
| 210 v8::Local<v8::Value> exception = data.GetValue(); | 213 v8::Local<v8::Value> exception = data.GetValue(); |
| 211 if (V8DOMWrapper::isWrapper(isolate, exception)) { | 214 if (V8DOMWrapper::isWrapper(isolate, exception)) { |
| 212 // Try to get the stack & location from a wrapped exception object (e.g. DOM
Exception). | 215 // Try to get the stack & location from a wrapped exception object (e.g. |
| 216 // DOMException). |
| 213 ASSERT(exception->IsObject()); | 217 ASSERT(exception->IsObject()); |
| 214 auto privateError = V8PrivateProperty::getDOMExceptionError(isolate); | 218 auto privateError = V8PrivateProperty::getDOMExceptionError(isolate); |
| 215 v8::Local<v8::Value> error = privateError.getOrUndefined( | 219 v8::Local<v8::Value> error = privateError.getOrUndefined( |
| 216 scriptState->context(), exception.As<v8::Object>()); | 220 scriptState->context(), exception.As<v8::Object>()); |
| 217 if (!error->IsUndefined()) | 221 if (!error->IsUndefined()) |
| 218 exception = error; | 222 exception = error; |
| 219 } | 223 } |
| 220 | 224 |
| 221 String errorMessage; | 225 String errorMessage; |
| 222 AccessControlStatus corsStatus = NotSharableCrossOrigin; | 226 AccessControlStatus corsStatus = NotSharableCrossOrigin; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 | 292 |
| 289 static void failedAccessCheckCallbackInMainThread(v8::Local<v8::Object> host, | 293 static void failedAccessCheckCallbackInMainThread(v8::Local<v8::Object> host, |
| 290 v8::AccessType type, | 294 v8::AccessType type, |
| 291 v8::Local<v8::Value> data) { | 295 v8::Local<v8::Value> data) { |
| 292 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 296 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 293 Frame* target = findFrame(isolate, host, data); | 297 Frame* target = findFrame(isolate, host, data); |
| 294 if (!target) | 298 if (!target) |
| 295 return; | 299 return; |
| 296 DOMWindow* targetWindow = target->domWindow(); | 300 DOMWindow* targetWindow = target->domWindow(); |
| 297 | 301 |
| 298 // FIXME: We should modify V8 to pass in more contextual information (context,
property, and object). | 302 // FIXME: We should modify V8 to pass in more contextual information (context, |
| 303 // property, and object). |
| 299 ExceptionState exceptionState(ExceptionState::UnknownContext, 0, 0, | 304 ExceptionState exceptionState(ExceptionState::UnknownContext, 0, 0, |
| 300 isolate->GetCurrentContext()->Global(), | 305 isolate->GetCurrentContext()->Global(), |
| 301 isolate); | 306 isolate); |
| 302 exceptionState.throwSecurityError( | 307 exceptionState.throwSecurityError( |
| 303 targetWindow->sanitizedCrossDomainAccessErrorMessage( | 308 targetWindow->sanitizedCrossDomainAccessErrorMessage( |
| 304 currentDOMWindow(isolate)), | 309 currentDOMWindow(isolate)), |
| 305 targetWindow->crossDomainAccessErrorMessage(currentDOMWindow(isolate))); | 310 targetWindow->crossDomainAccessErrorMessage(currentDOMWindow(isolate))); |
| 306 } | 311 } |
| 307 | 312 |
| 308 static bool codeGenerationCheckCallbackInMainThread( | 313 static bool codeGenerationCheckCallbackInMainThread( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 329 } | 334 } |
| 330 | 335 |
| 331 v8::Debug::SetLiveEditEnabled(isolate, false); | 336 v8::Debug::SetLiveEditEnabled(isolate, false); |
| 332 | 337 |
| 333 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped); | 338 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped); |
| 334 } | 339 } |
| 335 | 340 |
| 336 namespace { | 341 namespace { |
| 337 | 342 |
| 338 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { | 343 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { |
| 339 // Allocate() methods return null to signal allocation failure to V8, which sh
ould respond by throwing | 344 // Allocate() methods return null to signal allocation failure to V8, which |
| 340 // a RangeError, per http://www.ecma-international.org/ecma-262/6.0/#sec-creat
ebytedatablock. | 345 // should respond by throwing a RangeError, per |
| 346 // http://www.ecma-international.org/ecma-262/6.0/#sec-createbytedatablock. |
| 341 void* Allocate(size_t size) override { | 347 void* Allocate(size_t size) override { |
| 342 void* data; | 348 void* data; |
| 343 WTF::ArrayBufferContents::allocateMemoryOrNull( | 349 WTF::ArrayBufferContents::allocateMemoryOrNull( |
| 344 size, WTF::ArrayBufferContents::ZeroInitialize, data); | 350 size, WTF::ArrayBufferContents::ZeroInitialize, data); |
| 345 return data; | 351 return data; |
| 346 } | 352 } |
| 347 | 353 |
| 348 void* AllocateUninitialized(size_t size) override { | 354 void* AllocateUninitialized(size_t size) override { |
| 349 void* data; | 355 void* data; |
| 350 WTF::ArrayBufferContents::allocateMemoryOrNull( | 356 WTF::ArrayBufferContents::allocateMemoryOrNull( |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 | 436 |
| 431 void V8Initializer::shutdownMainThread() { | 437 void V8Initializer::shutdownMainThread() { |
| 432 ASSERT(isMainThread()); | 438 ASSERT(isMainThread()); |
| 433 v8::Isolate* isolate = V8PerIsolateData::mainThreadIsolate(); | 439 v8::Isolate* isolate = V8PerIsolateData::mainThreadIsolate(); |
| 434 V8PerIsolateData::willBeDestroyed(isolate); | 440 V8PerIsolateData::willBeDestroyed(isolate); |
| 435 V8PerIsolateData::destroy(isolate); | 441 V8PerIsolateData::destroy(isolate); |
| 436 } | 442 } |
| 437 | 443 |
| 438 static void reportFatalErrorInWorker(const char* location, | 444 static void reportFatalErrorInWorker(const char* location, |
| 439 const char* message) { | 445 const char* message) { |
| 440 // FIXME: We temporarily deal with V8 internal error situations such as out-of
-memory by crashing the worker. | 446 // FIXME: We temporarily deal with V8 internal error situations such as |
| 447 // out-of-memory by crashing the worker. |
| 441 CRASH(); | 448 CRASH(); |
| 442 } | 449 } |
| 443 | 450 |
| 444 static void messageHandlerInWorker(v8::Local<v8::Message> message, | 451 static void messageHandlerInWorker(v8::Local<v8::Message> message, |
| 445 v8::Local<v8::Value> data) { | 452 v8::Local<v8::Value> data) { |
| 446 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 453 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 447 V8PerIsolateData* perIsolateData = V8PerIsolateData::from(isolate); | 454 V8PerIsolateData* perIsolateData = V8PerIsolateData::from(isolate); |
| 448 | 455 |
| 449 // During the frame teardown, there may not be a valid context. | 456 // During the frame teardown, there may not be a valid context. |
| 450 ScriptState* scriptState = ScriptState::current(isolate); | 457 ScriptState* scriptState = ScriptState::current(isolate); |
| 451 if (!scriptState->contextIsValid()) | 458 if (!scriptState->contextIsValid()) |
| 452 return; | 459 return; |
| 453 | 460 |
| 454 // Exceptions that occur in error handler should be ignored since in that case | 461 // Exceptions that occur in error handler should be ignored since in that case |
| 455 // WorkerGlobalScope::dispatchErrorEvent will send the exception to the worker
object. | 462 // WorkerGlobalScope::dispatchErrorEvent will send the exception to the worker |
| 463 // object. |
| 456 if (perIsolateData->isReportingException()) | 464 if (perIsolateData->isReportingException()) |
| 457 return; | 465 return; |
| 458 | 466 |
| 459 perIsolateData->setReportingException(true); | 467 perIsolateData->setReportingException(true); |
| 460 | 468 |
| 461 ExecutionContext* context = scriptState->getExecutionContext(); | 469 ExecutionContext* context = scriptState->getExecutionContext(); |
| 462 std::unique_ptr<SourceLocation> location = | 470 std::unique_ptr<SourceLocation> location = |
| 463 SourceLocation::fromMessage(isolate, message, context); | 471 SourceLocation::fromMessage(isolate, message, context); |
| 464 ErrorEvent* event = | 472 ErrorEvent* event = |
| 465 ErrorEvent::create(toCoreStringWithNullCheck(message->Get()), | 473 ErrorEvent::create(toCoreStringWithNullCheck(message->Get()), |
| 466 std::move(location), &scriptState->world()); | 474 std::move(location), &scriptState->world()); |
| 467 | 475 |
| 468 AccessControlStatus corsStatus = message->IsSharedCrossOrigin() | 476 AccessControlStatus corsStatus = message->IsSharedCrossOrigin() |
| 469 ? SharableCrossOrigin | 477 ? SharableCrossOrigin |
| 470 : NotSharableCrossOrigin; | 478 : NotSharableCrossOrigin; |
| 471 | 479 |
| 472 // If execution termination has been triggered as part of constructing | 480 // If execution termination has been triggered as part of constructing |
| 473 // the error event from the v8::Message, quietly leave. | 481 // the error event from the v8::Message, quietly leave. |
| 474 if (!isolate->IsExecutionTerminating()) { | 482 if (!isolate->IsExecutionTerminating()) { |
| 475 V8ErrorHandler::storeExceptionOnErrorEventWrapper( | 483 V8ErrorHandler::storeExceptionOnErrorEventWrapper( |
| 476 scriptState, event, data, scriptState->context()->Global()); | 484 scriptState, event, data, scriptState->context()->Global()); |
| 477 scriptState->getExecutionContext()->dispatchErrorEvent(event, corsStatus); | 485 scriptState->getExecutionContext()->dispatchErrorEvent(event, corsStatus); |
| 478 } | 486 } |
| 479 | 487 |
| 480 perIsolateData->setReportingException(false); | 488 perIsolateData->setReportingException(false); |
| 481 } | 489 } |
| 482 | 490 |
| 483 static const int kWorkerMaxStackSize = 500 * 1024; | 491 static const int kWorkerMaxStackSize = 500 * 1024; |
| 484 | 492 |
| 485 // This function uses a local stack variable to determine the isolate's stack li
mit. AddressSanitizer may | 493 // This function uses a local stack variable to determine the isolate's stack |
| 486 // relocate that local variable to a fake stack, which may lead to problems duri
ng JavaScript execution. | 494 // limit. AddressSanitizer may relocate that local variable to a fake stack, |
| 487 // Therefore we disable AddressSanitizer for V8Initializer::initializeWorker(). | 495 // which may lead to problems during JavaScript execution. Therefore we disable |
| 496 // AddressSanitizer for V8Initializer::initializeWorker(). |
| 488 NO_SANITIZE_ADDRESS | 497 NO_SANITIZE_ADDRESS |
| 489 void V8Initializer::initializeWorker(v8::Isolate* isolate) { | 498 void V8Initializer::initializeWorker(v8::Isolate* isolate) { |
| 490 initializeV8Common(isolate); | 499 initializeV8Common(isolate); |
| 491 | 500 |
| 492 isolate->AddMessageListener(messageHandlerInWorker); | 501 isolate->AddMessageListener(messageHandlerInWorker); |
| 493 isolate->SetFatalErrorHandler(reportFatalErrorInWorker); | 502 isolate->SetFatalErrorHandler(reportFatalErrorInWorker); |
| 494 | 503 |
| 495 uint32_t here; | 504 uint32_t here; |
| 496 isolate->SetStackLimit(reinterpret_cast<uintptr_t>( | 505 isolate->SetStackLimit(reinterpret_cast<uintptr_t>( |
| 497 &here - kWorkerMaxStackSize / sizeof(uint32_t*))); | 506 &here - kWorkerMaxStackSize / sizeof(uint32_t*))); |
| 498 isolate->SetPromiseRejectCallback(promiseRejectHandlerInWorker); | 507 isolate->SetPromiseRejectCallback(promiseRejectHandlerInWorker); |
| 499 } | 508 } |
| 500 | 509 |
| 501 } // namespace blink | 510 } // namespace blink |
| OLD | NEW |