void RejectedPromises::handlerAdded(v8::PromiseRejectMessage data) { // First look it up in the pending messages and fast return, it'll be covered // by processQueue(). for (auto it = m_queue.begin(); it != m_queue.end(); ++it) { if (!(*it)->isCollected() && (*it)->hasPromise(data.GetPromise())) { m_queue.remove(it); return; } } // Then look it up in the reported errors. for (size_t i = 0; i < m_reportedAsErrors.size(); ++i) { std::unique_ptr<Message>& message = m_reportedAsErrors.at(i); if (!message->isCollected() && message->hasPromise(data.GetPromise())) { message->makePromiseStrong(); Platform::current() ->currentThread() ->scheduler() ->timerTaskRunner() ->postTask(BLINK_FROM_HERE, WTF::bind(&RejectedPromises::revokeNow, RefPtr<RejectedPromises>(this), passed(std::move(message)))); m_reportedAsErrors.remove(i); return; } } }
static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data) { ASSERT(isMainThread()); if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { rejectedPromisesOnMainThread().handlerAdded(data); return; } ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); v8::Local<v8::Promise> promise = data.GetPromise(); v8::Isolate* isolate = promise->GetIsolate(); // There is no entered window during microtask callbacks from V8, // thus we call toDOMWindow() instead of enteredDOMWindow(). LocalDOMWindow* window = currentDOMWindow(isolate); if (!window || !window->isCurrentlyDisplayedInFrame()) return; v8::Local<v8::Value> exception = data.GetValue(); if (V8DOMWrapper::isWrapper(isolate, exception)) { // Try to get the stack & location from a wrapped exception object (e.g. DOMException). ASSERT(exception->IsObject()); v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(exception); v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj, V8HiddenValue::error(isolate)); if (!error.IsEmpty()) exception = error; } int scriptId = 0; int lineNumber = 0; int columnNumber = 0; String resourceName; String errorMessage; RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; v8::Local<v8::Message> message = v8::Exception::CreateMessage(exception); if (!message.IsEmpty()) { if (v8Call(message->GetLineNumber(isolate->GetCurrentContext()), lineNumber) && v8Call(message->GetStartColumn(isolate->GetCurrentContext()), columnNumber)) ++columnNumber; resourceName = extractResourceName(message, window->document()); errorMessage = toCoreStringWithNullCheck(message->Get()); callStack = extractCallStack(isolate, message, &scriptId); } else if (!exception.IsEmpty() && exception->IsInt32()) { // For Smi's the message would be empty. errorMessage = "Uncaught " + String::number(exception.As<v8::Integer>()->Value()); } String messageForConsole = extractMessageForConsole(isolate, data.GetValue()); if (!messageForConsole.isEmpty()) errorMessage = "Uncaught " + messageForConsole; ScriptState* scriptState = ScriptState::current(isolate); rejectedPromisesOnMainThread().rejectedWithNoHandler(scriptState, data, errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack); }
void RejectedPromises::rejectedWithNoHandler( ScriptState* scriptState, v8::PromiseRejectMessage data, const String& errorMessage, std::unique_ptr<SourceLocation> location, AccessControlStatus corsStatus) { m_queue.append(Message::create(scriptState, data.GetPromise(), data.GetValue(), errorMessage, std::move(location), corsStatus)); }
static void promiseRejectHandler(v8::PromiseRejectMessage data, RejectedPromises& rejectedPromises, const String& fallbackResourceName) { if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { rejectedPromises.handlerAdded(data); return; } ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); v8::Local<v8::Promise> promise = data.GetPromise(); v8::Isolate* isolate = promise->GetIsolate(); ScriptState* scriptState = ScriptState::current(isolate); v8::Local<v8::Value> exception = data.GetValue(); if (V8DOMWrapper::isWrapper(isolate, exception)) { // Try to get the stack & location from a wrapped exception object (e.g. DOMException). ASSERT(exception->IsObject()); v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(exception); v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(scriptState, obj, V8HiddenValue::error(isolate)); if (!error.IsEmpty()) exception = error; } int scriptId = 0; int lineNumber = 0; int columnNumber = 0; String resourceName = fallbackResourceName; String errorMessage; AccessControlStatus corsStatus = NotSharableCrossOrigin; RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; v8::Local<v8::Message> message = v8::Exception::CreateMessage(isolate, exception); if (!message.IsEmpty()) { V8StringResource<> v8ResourceName(message->GetScriptOrigin().ResourceName()); if (v8ResourceName.prepare()) resourceName = v8ResourceName; scriptId = message->GetScriptOrigin().ScriptID()->Value(); if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber) && v8Call(message->GetStartColumn(scriptState->context()), columnNumber)) ++columnNumber; // message->Get() can be empty here. https://crbug.com/450330 errorMessage = toCoreStringWithNullCheck(message->Get()); callStack = extractCallStack(isolate, message, &scriptId); if (message->IsSharedCrossOrigin()) corsStatus = SharableCrossOrigin; } String messageForConsole = extractMessageForConsole(isolate, data.GetValue()); if (!messageForConsole.isEmpty()) errorMessage = "Uncaught " + messageForConsole; rejectedPromises.rejectedWithNoHandler(scriptState, data, errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack, corsStatus); }
static void promiseRejectHandler(v8::PromiseRejectMessage data, RejectedPromises& rejectedPromises, ScriptState* scriptState) { if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { rejectedPromises.handlerAdded(data); return; } ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); v8::Local<v8::Promise> promise = data.GetPromise(); v8::Isolate* isolate = promise->GetIsolate(); ExecutionContext* context = scriptState->getExecutionContext(); v8::Local<v8::Value> exception = data.GetValue(); if (V8DOMWrapper::isWrapper(isolate, exception)) { // Try to get the stack & location from a wrapped exception object (e.g. // DOMException). ASSERT(exception->IsObject()); auto privateError = V8PrivateProperty::getDOMExceptionError(isolate); v8::Local<v8::Value> error = privateError.getOrUndefined( scriptState->context(), exception.As<v8::Object>()); if (!error->IsUndefined()) exception = error; } String errorMessage; AccessControlStatus corsStatus = NotSharableCrossOrigin; std::unique_ptr<SourceLocation> location; v8::Local<v8::Message> message = v8::Exception::CreateMessage(isolate, exception); if (!message.IsEmpty()) { // message->Get() can be empty here. https://crbug.com/450330 errorMessage = toCoreStringWithNullCheck(message->Get()); location = SourceLocation::fromMessage(isolate, message, context); if (message->IsSharedCrossOrigin()) corsStatus = SharableCrossOrigin; } else { location = SourceLocation::create(context->url().getString(), 0, 0, nullptr); } String messageForConsole = extractMessageForConsole(isolate, data.GetValue()); if (!messageForConsole.isEmpty()) errorMessage = "Uncaught " + messageForConsole; rejectedPromises.rejectedWithNoHandler(scriptState, data, errorMessage, std::move(location), corsStatus); }
static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage data) { v8::Local<v8::Promise> promise = data.GetPromise(); // Bail out if called during context initialization. v8::Isolate* isolate = promise->GetIsolate(); ScriptState* scriptState = ScriptState::current(isolate); if (!scriptState->contextIsValid()) return; ExecutionContext* executionContext = scriptState->executionContext(); if (!executionContext) return; ASSERT(executionContext->isWorkerGlobalScope()); WorkerScriptController* scriptController = toWorkerGlobalScope(executionContext)->script(); ASSERT(scriptController); if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { scriptController->rejectedPromises()->handlerAdded(data); return; } ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler); int scriptId = 0; int lineNumber = 0; int columnNumber = 0; String resourceName; String errorMessage; v8::Local<v8::Message> message = v8::Exception::CreateMessage(data.GetValue()); if (!message.IsEmpty()) { TOSTRING_VOID(V8StringResource<>, resourceName, message->GetScriptOrigin().ResourceName()); scriptId = message->GetScriptOrigin().ScriptID()->Value(); if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber) && v8Call(message->GetStartColumn(scriptState->context()), columnNumber)) ++columnNumber; // message->Get() can be empty here. https://crbug.com/450330 errorMessage = toCoreStringWithNullCheck(message->Get()); } scriptController->rejectedPromises()->rejectedWithNoHandler(scriptState, data, errorMessage, resourceName, scriptId, lineNumber, columnNumber, nullptr); }
static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data) { ASSERT(isMainThread()); v8::Local<v8::Promise> promise = data.GetPromise(); v8::Isolate* isolate = promise->GetIsolate(); // There is no entered window during microtask callbacks from V8, // thus we call toDOMWindow() instead of enteredDOMWindow(). LocalDOMWindow* window = currentDOMWindow(isolate); if (!window || !window->isCurrentlyDisplayedInFrame()) return; promiseRejectHandler(data, rejectedPromisesOnMainThread(), window->document() ? window->document()->url() : String()); }
static void promiseRejectHandlerInWorker(v8::PromiseRejectMessage data) { v8::Local<v8::Promise> promise = data.GetPromise(); // Bail out if called during context initialization. v8::Isolate* isolate = promise->GetIsolate(); ScriptState* scriptState = ScriptState::current(isolate); if (!scriptState->contextIsValid()) return; ExecutionContext* executionContext = scriptState->getExecutionContext(); if (!executionContext) return; ASSERT(executionContext->isWorkerGlobalScope()); WorkerOrWorkletScriptController* scriptController = toWorkerGlobalScope(executionContext)->scriptController(); ASSERT(scriptController); promiseRejectHandler(data, *scriptController->getRejectedPromises(), scriptState); }
static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data) { ASSERT(isMainThread()); v8::Local<v8::Promise> promise = data.GetPromise(); v8::Isolate* isolate = promise->GetIsolate(); // TODO(ikilpatrick): Remove this check, extensions tests that use // extensions::ModuleSystemTest incorrectly don't have a valid script state. LocalDOMWindow* window = currentDOMWindow(isolate); if (!window || !window->isCurrentlyDisplayedInFrame()) return; // Bail out if called during context initialization. ScriptState* scriptState = ScriptState::current(isolate); if (!scriptState->contextIsValid()) return; promiseRejectHandler(data, rejectedPromisesOnMainThread(), scriptState); }
void RejectedPromises::rejectedWithNoHandler(ScriptState* scriptState, v8::PromiseRejectMessage data, const String& errorMessage, const String& resourceName, int scriptId, int lineNumber, int columnNumber, PassRefPtrWillBeRawPtr<ScriptCallStack> callStack, AccessControlStatus corsStatus) { m_queue.append(Message::create(scriptState, data.GetPromise(), data.GetValue(), errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack, corsStatus)); }