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 |